#include "Scene/Scene.h"
#include "Scene/Entity.h"


#include "Renderer/renderCommand.h"
#include "Renderer/framebuffer.h"

#include <glm/glm.hpp>
#include "Debug/GuiHelper.h"
#include "Scene/Scene.h"
#include "Core/application.h"

namespace CC
{

    struct MyConvertPointerSizeT
    {
        union
        {
            const void *m_ptr;
            size_t m_int;
        };
    };

    bool shapePointerCompareFunc(const btCollisionObject *colA, const btCollisionObject *colB)
    {
        MyConvertPointerSizeT a, b;
        a.m_ptr = colA->getCollisionShape();
        b.m_ptr = colB->getCollisionShape();
        return (a.m_int < b.m_int);
    }

    float Scene::m_MouseX = 0.0;
    float Scene::m_MouseY = 0.0;

    Scene::Scene()
    {
        InitPhysicesWorld();
        InitFontUnicode();

        m_root = CreateRoot("root");
        m_OrthographicCamera = nullptr;
        m_PerspectiveCamera = nullptr;
        m_EditPerspectiveCamera = nullptr;
        m_OrthographicCamera3d = nullptr;
    }

    Scene::~Scene()
    {
        CC_CORE_INFO("Scene::~Scene()\n");
        m_EntityMap.clear();

        if (m_CurrentFont)
        {
            delete m_CurrentFont;
            m_CurrentFont = nullptr;
        }

        if (m_OrthographicCamera)
        {
            delete m_OrthographicCamera;
            m_OrthographicCamera = nullptr;
        }
        if (m_OrthographicCamera3d)
        {
            delete m_OrthographicCamera3d;
            m_OrthographicCamera3d = nullptr;
        }
        if (m_PerspectiveCamera)
        {
            delete m_PerspectiveCamera;
            m_PerspectiveCamera = nullptr;
        }
        if (m_EditPerspectiveCamera)
        {
            delete m_EditPerspectiveCamera;
            m_EditPerspectiveCamera = nullptr;
        }

        if (m_FramebufferData) {
            delete m_FramebufferData;
            m_FramebufferData = nullptr;
        }

        if (m_FramebufferData2D) {
            delete m_FramebufferData2D;
            m_FramebufferData2D = nullptr;
        }

        ReleasePhysicesWorld();
    }

    Entity *Scene::CreateEntity(const std::string &name, Entity *parent)
    {
        return CreateEntityWithUUID(UUID(), name, parent);
    }

    Entity *Scene::CreateEntityWithUUID(UUID uuid, const std::string &name, Entity *parent)
    {
        Entity *entity = new Entity(this);
        IDComponent* idc = new IDComponent(uuid);
        entity->AddOrReplaceComponent<IDComponent>(idc);

        TransformComponent* tc = new TransformComponent();
        entity->AddOrReplaceComponent<TransformComponent>(tc);

        TagComponent* tag = new TagComponent(name.empty() ? "Entity" : name);
        entity->AddOrReplaceComponent<TagComponent>(tag);

        // m_EntityMap[uuid] = entity;

        if (!parent)
        {
           // m_root->AddChild(entity);
        }
        else
        {
            parent->AddChild(entity);
        }

        return entity;
    }

    Entity *Scene::CreateRoot(const std::string &name)
    {
        UUID uuid = UUID();
        Entity *entity = new Entity(this);

        IDComponent* idc = new IDComponent(uuid);
        entity->AddOrReplaceComponent<IDComponent>(idc);

        TransformComponent* tc = new TransformComponent();
        entity->AddOrReplaceComponent<TransformComponent>(tc);

        TagComponent* tag = new TagComponent(name.empty() ? "Entity" : name);
        entity->AddOrReplaceComponent<TagComponent>(tag);

        // m_EntityMap[uuid] = entity;
        return entity;
    }

    void Scene::DestroyEntity(Entity *entity)
    {
        CC_ASSERT(entity != nullptr, "ASSERT: Scene::DestroyEntity entity=null\n");

        // m_EntityMap.erase(entity->GetUUID());

        if (entity->GetParent())
        {
            entity->GetParent()->RemoveChild(entity);
        }
        else
        {
            delete entity;
            entity = nullptr;
        }
    }

    Entity *Scene::FindEntityByName(const std::string name)
    {
        CC_ASSERT(m_root != nullptr, "ASSERT: Scene::FindEntityByName m_root=null\n");

        Entity* e = FindEntityByNameRecursion(name, m_root);

        return e;
    }

    Entity * Scene::FindEntityByRigidBoy(const btRigidBody * body)
    {
        CC_ASSERT(m_root != nullptr, "ASSERT: Scene::FindEntityByRigidBoy m_root=null\n");

        Entity* e = FindEntityByRigidBoyRecursion(body, m_root);

        return e;
    }

    CC::Entity *Scene::FindEntityByCamera2d()
    {
        CC_ASSERT(m_root != nullptr, "ASSERT: Scene::FindEntityByCamera2d m_root=null\n");

        for (int i = 0; i < m_root->GetChildCount(); i++)
        {
            Entity *p = m_root->GetChild(i);
            if (p->HasComponent(ComponentType_Camera) && ((p->GetComponent<CameraComponent>(ComponentType_Camera))->Type2d))
            {
                return p;
            }
        }
        return nullptr;
    }

    CC::Entity *Scene::FindEntityByCamera3d()
    {
        CC_ASSERT(m_root != nullptr, "ASSERT: Scene::FindEntityByCamera3d m_root=null\n");

        for (int i = 0; i < m_root->GetChildCount(); i++)
        {
            Entity *p = m_root->GetChild(i);
            if (p->HasComponent(ComponentType_Camera) && !((p->GetComponent<CameraComponent>(ComponentType_Camera))->Type2d))
            {
                //CC_CORE_INFO("-FindEntityByCamera3d: %s\n", p->GetComponent<TagComponent>(ComponentType_Tag)->Tag.c_str());
                return p;
            }
        }
        return nullptr;
    }

    void Scene::OnRuntimeStart()
    {
        m_IsRunning = true;

        Renderer2D::ResetStats();
        Renderer3D::ResetStats();

        RenderCommand::SetClearColor(m_ClearColor);
        // RenderCommand::Clear();

        OnSimulationStart();
    }

    void Scene::OnRuntimeStop()
    {
        m_IsRunning = false;

        OnSimulationStop();
    }

    void Scene::OnSimulationStart()
    {
        OnPhysics3DStart();
    }

    void Scene::OnSimulationStop()
    {
        OnPhysics3DStop();
    }

    void Scene::OnPhysics3DStart()
    {
    }

    void Scene::OnPhysics3DStop()
    {
    }

    //renderscene="","2d","3d", for framebuffer
    void Scene::OnUpdateRuntime(Timestep ts, std::string renderscene)
    {
        if (!m_IsPaused || m_StepFrames-- > 0)
        {
        }

        // Render 2D
        Camera *mainCamera2d = nullptr; //(Camera *)m_OrthographicCamera;
        Camera *mainCamera3d = nullptr; //(Camera *)m_PerspectiveCamera;
        glm::mat4 cameraTransform2d;
        glm::mat4 cameraTransform3d;

        Entity *e1 = m_mainCamera2dEntity;// FindEntityByCamera2d();
        Entity *e2 = m_mainCamera3dEntity;// FindEntityByCamera3d();

        if (e1)
        {
            CameraComponent* cameraComponent = e1->GetComponent<CameraComponent>(ComponentType_Camera);
            mainCamera2d = (Camera *)cameraComponent->camera;
            cameraTransform2d = (e1->GetComponent<TransformComponent>(ComponentType_Transform))->GetTransform();
        }

        if (e2)
        {
            if (m_UseEditCamera) {
                mainCamera3d = (Camera *)m_EditPerspectiveCamera;                
            }
            else {
                CameraComponent* cameraComponent = e2->GetComponent<CameraComponent>(ComponentType_Camera);
                mainCamera3d = (Camera *)cameraComponent->camera;
            }
            if (m_PerspectiveCamera) {
                m_mainCamera3d = (PerspectiveCamera *)mainCamera3d;
            }
            else {
               // m_mainCamera3d = m_OrthographicCamera3d;
            }
            
            cameraTransform3d = e2->GetComponent<TransformComponent>(ComponentType_Transform)->GetTransform();
        }

        if ("" == renderscene) {
            OnUpdateAnimationProperty(ts);
            OnUpdateAnimationPropertyGroup(ts);
            OnUpdateScript(ts);
            OnUpdateSimulation(ts, mainCamera3d);
            OnUpdateTipInfo(ts);
        }        

        // Render 3D
        if (mainCamera3d && ("" == renderscene || "3d" == renderscene))
        {
            mainCamera3d->OnUpdate(ts);
            RenderCommand::ClearDepth();
            RenderCommand::Clear();

            Renderer3D::SetShadowDrawState(true);
            //RenderScene3D(mainCamera3d, cameraTransform3d, ts);
            {
                CC_ASSERT(m_root != nullptr, "ASSERT: Scene::RenderScene3D m_root=null\n");
                Renderer3D::BeginScene(mainCamera3d, cameraTransform3d, m_FramebufferData, false, "opaque");
                RenderEnityty3D(m_root, glm::mat4(1.0), glm::vec3(1.0, 1.0, 1.0), ts, "opaque");
                Renderer3D::EndScene();

                Renderer3D::BeginScene(mainCamera3d, cameraTransform3d, m_FramebufferData, false, "transparent");
                RenderEnityty3D(m_root, glm::mat4(1.0), glm::vec3(1.0, 1.0, 1.0), ts, "transparent");
                Renderer3D::EndScene();
            }

            Renderer3D::SetShadowDrawState(false);
            RenderScene3D(mainCamera3d, cameraTransform3d, ts);

            /*{
                // draw arrow axis
                Renderer3D::BeginScene(mainCamera3d, cameraTransform3d, m_FramebufferData, true);//del
                if (m_MoveAxisDisplay) {

                    if (m_ArrowGlobalAxisX) {
                        auto transformParent = m_ArrowGlobalAxisX->GetComponent<TransformComponent>(ComponentType_Transform);
                        transformParent->Translation = GetEntityRigidBodyTransform(m_ArrowGlobalAxisX);

                        Entity * e = m_ArrowGlobalAxisX->GetChild(0);

                        auto material = e->GetComponent<MeshModelMaterialComponent>(ComponentType_MeshModelMaterial);
                        auto mesh = e->GetComponent<MeshComponent>(ComponentType_Mesh);
                        auto transform = e->GetComponent<TransformComponent>(ComponentType_Transform);

                        Renderer3D::DrawModelNoAnim(transformParent->GetTransform() * transform->GetTransform(), *material, *mesh, (int)e);
                    }

                    if (m_ArrowGlobalAxisY) {
                        auto transformParent = m_ArrowGlobalAxisY->GetComponent<TransformComponent>(ComponentType_Transform);
                        transformParent->Translation = GetEntityRigidBodyTransform(m_ArrowGlobalAxisY);

                        Entity * e = m_ArrowGlobalAxisY->GetChild(0);

                        auto material = e->GetComponent<MeshModelMaterialComponent>(ComponentType_MeshModelMaterial);
                        auto mesh = e->GetComponent<MeshComponent>(ComponentType_Mesh);
                        auto transform = e->GetComponent<TransformComponent>(ComponentType_Transform);

                        Renderer3D::DrawModelNoAnim(transformParent->GetTransform() * transform->GetTransform(), *material, *mesh, (int)e);
                    }

                    if (m_ArrowGlobalAxisZ) {
                        auto transformParent = m_ArrowGlobalAxisZ->GetComponent<TransformComponent>(ComponentType_Transform);
                        transformParent->Translation = GetEntityRigidBodyTransform(m_ArrowGlobalAxisZ);

                        Entity * e = m_ArrowGlobalAxisZ->GetChild(0);

                        auto material = e->GetComponent<MeshModelMaterialComponent>(ComponentType_MeshModelMaterial);
                        auto mesh = e->GetComponent<MeshComponent>(ComponentType_Mesh);
                        auto transform = e->GetComponent<TransformComponent>(ComponentType_Transform);

                        Renderer3D::DrawModelNoAnim(transformParent->GetTransform() * transform->GetTransform(), *material, *mesh, (int)e);
                    }

                }
                Renderer3D::EndScene();
            }*/
        }
        else {
            RenderCommand::ClearDepth();
            RenderCommand::Clear();
        }
        

        if (m_dynamicsWorld && m_DebugPhysics && mainCamera3d)
        {
            RenderScene3DDebugPhysics(mainCamera3d, cameraTransform3d, ts);
        }

        if (mainCamera2d && ("" == renderscene || "2d" == renderscene))
        {
            mainCamera2d->OnUpdate(ts);

            RenderScene2D(mainCamera2d, cameraTransform2d, ts);
        }
    }

    void Scene::OnUpdateSimulation(Timestep ts, Camera *camera)
    {
        if (!m_dynamicsWorld)
            return;
        if (!m_IsSanbox) return;
        m_dynamicsWorld->stepSimulation(1.f / 60.f, 10);

        onContactTestRecursionOne(m_root);
    }

    void Scene::OnUpdateScript(Timestep ts)
    {
        CC_ASSERT(m_root != nullptr, "ASSERT: Scene::FindEntityByName m_root=null\n");
        OnUpdateScriptRecursion(m_root, ts);
    }

    void Scene::OnUpdateAnimationProperty(Timestep ts)
    {
        CC_ASSERT(m_root != nullptr, "ASSERT: Scene::FindEntityByName m_root=null\n");

        for (int i = 0; i < m_AnimationPropertyes.size(); i++) {
            if (m_AnimationPropertyes[i] && *m_AnimationPropertyes[i]) {
                (*m_AnimationPropertyes[i])->Update(ts);

                if ((*m_AnimationPropertyes[i])->IsDestory()) {
                    delete *m_AnimationPropertyes[i];
                    *m_AnimationPropertyes[i] = NULL;
                    m_AnimationPropertyes.erase(m_AnimationPropertyes.begin() + i);
                    i--;
                }
            }
            else {
                m_AnimationPropertyes.erase(m_AnimationPropertyes.begin() + i);
                i--;
            }
        }
    }

    void Scene::OnUpdateAnimationPropertyGroup(Timestep ts)
    {
        for (int i = 0; i < m_AnimationPropertyeGroups.size(); i++) {
            if (m_AnimationPropertyeGroups[i]) {
                m_AnimationPropertyeGroups[i]->Update(ts);
            }
        }
    }

    void Scene::OnUpdateTipInfo(Timestep ts)
    {
        if (m_ArrowGlobalAxisX && m_ArrowGlobalAxisY && m_ArrowGlobalAxisZ) {
            if (m_CurrentSelectEntity) {
                TagComponent* tagX = m_ArrowGlobalAxisX->GetComponent<TagComponent>(ComponentType_Tag);
                tagX->Visible = true;

                TagComponent* tagY = m_ArrowGlobalAxisY->GetComponent<TagComponent>(ComponentType_Tag);
                tagY->Visible = true;

                TagComponent* tagZ = m_ArrowGlobalAxisZ->GetComponent<TagComponent>(ComponentType_Tag);
                tagZ->Visible = true;

                glm::vec3 Translation = m_CurrentSelectEntity->GetComponent<TransformComponent>(ComponentType_Transform)->Translation;

                SetEntityTrans(m_ArrowGlobalAxisX, Translation);
                SetEntityTrans(m_ArrowGlobalAxisY, Translation);
                SetEntityTrans(m_ArrowGlobalAxisZ, Translation);
            }
        }
        
    }

    void Scene::OnUpdateScriptRecursion(Entity *parent, Timestep ts)
    {
        if (!parent)
            return;
        int len = parent->GetChildCount();
        for (int i = 0; i < len; i++)
        {
            Entity *child = parent->GetChild(i);

            if (child->HasComponent(ComponentType_Script))
            {
                auto script = child->GetComponent<ScriptComponent>(ComponentType_Script);
                if (script->ScriptObject)
                    script->ScriptObject->Update(ts);
            }

            if (child->GetChildCount() > 0)
                OnUpdateScriptRecursion(child, ts);
        }
    }

    void Scene::onContactTestRecursionOne(Entity *parent)
    {
        if (!parent)
            return;
        int len = parent->GetChildCount();
        for (int i = 0; i < len; i++)
        {
            Entity *child = parent->GetChild(i);

            if (child->HasComponent(ComponentType_RigidBody)) {
                onContactTestRecursion(child, m_root);
                //end check is contact

                auto c = child->GetComponent<RigidBodyComponent>(ComponentType_RigidBody);
                if (c->RigidBodyData.CallBack.CollisionFlagOneFrame) {
                    c->RigidBodyData.CallBack.CollisionFlagOneFrame = false;
                }
                else {
                    // no contact
                    if (child->HasComponent(ComponentType_Script)) {
                        auto script = child->GetComponent<ScriptComponent>(ComponentType_Script);
                        if (script->ScriptObject)
                            script->ScriptObject->onNoContactTest();
                    }
                }
            }

            if (child->GetChildCount() > 0)
                onContactTestRecursionOne(child);
        }
    }

    void Scene::onContactTestRecursion(Entity *current, Entity *other)
    {
        if (!current || !other)
            return;

        int len = other->GetChildCount();
        for (int i = 0; i < len; i++)
        {
            Entity *child = other->GetChild(i);
            if (child == current) continue;
        
            if (child->HasComponent(ComponentType_RigidBody))
            {
                auto c = current->GetComponent<RigidBodyComponent>(ComponentType_RigidBody);
                auto c1 = child->GetComponent<RigidBodyComponent>(ComponentType_RigidBody);

                if (RigidBodyShapeType_Box == c->RigidBodyData.RigidBodyShapeTypeValue
                    && RigidBodyShapeType_Box == c1->RigidBodyData.RigidBodyShapeTypeValue) {
                    m_dynamicsWorld->contactPairTest(c->RigidBodyData.BtRigidBody, c1->RigidBodyData.BtRigidBody, c->RigidBodyData.CallBack);

                    if (c->RigidBodyData.CallBack.CollisionFlag) {
                        c->RigidBodyData.CallBack.CollisionFlag = false;
                        // CC_CORE_INFO("onContactTestRecursion %s %s\n", child->GetComponent<CC::TagComponent>().Tag.c_str(), two->GetComponent<CC::TagComponent>().Tag.c_str());

                        if (current->HasComponent(ComponentType_Script)) {
                            auto script = current->GetComponent<ScriptComponent>(ComponentType_Script);
                            if (script->ScriptObject)
                                script->ScriptObject->onContactTest(current, child);
                        }
                    }
                }
                else {
                    ;
                }
                
            }            

            if (child->GetChildCount() > 0)
                onContactTestRecursion(current, child);
        }
    }

    void Scene::OnEventScriptRecursion(Entity *parent, Event &e)
    {
        if (!parent)
            return;
        int len = parent->GetChildCount();
        for (int i = 0; i < len; i++)
        {
            Entity *child = parent->GetChild(i);

            if (child->HasComponent(ComponentType_Script))
            {
                auto script = child->GetComponent<ScriptComponent>(ComponentType_Script);
                if (script->ScriptObject)
                    script->ScriptObject->OnEvent(e);
            }

            if (child->GetChildCount() > 0)
                OnEventScriptRecursion(child, e);
        }
    }

    void Scene::OnEventMouseAreaRecursion(Entity *parent, Event &e)
    {
        if (!parent)
            return;
        //if (m_entityHasFocusMouse && e.GetEventType() != MouseButtonPressedEvent::GetStaticType())
        //    return;

        int len = parent->GetChildCount();
        for (int i = len-1; i >= 0; --i)
        {
            Entity *child = parent->GetChild(i);

            if (child->HasComponent(ComponentType_MouseArea))
            {                
                auto t = child->GetComponent<TransformComponent>(ComponentType_Transform);
                if (m_MouseX < t->Translation[0] || m_MouseX > t->Translation[0] + t->Scale[0]
                    || m_MouseY < t->Translation[1] || m_MouseY > t->Translation[1] + t->Scale[1]) {
                    //outside
                }
                else {
                    // inside
                    auto c = child->GetComponent<MouseAreaComponent>(ComponentType_MouseArea);
                    c->OnEvent(e, child);
                    e.Handled = true;
                    m_entityHasFocusMouse = child;

                    if (m_entityHasFocusMouse && e.GetEventType() == MouseButtonReleasedEvent::GetStaticType())
                    {
                        m_entityHasFocusMouse = nullptr;
                    }
                    return;
                }                
            }

            if (child->GetChildCount() > 0) {
                OnEventMouseAreaRecursion(child, e);
                if (e.Handled) {
                    return;
                }
            }
        }
    }

    void Scene::OnMouseButtonPressedForButton(Event* event, Entity* e)
    {
        auto c = e->GetComponent<Material2DComponent>(ComponentType_Material2D);
        c->Color = { 0.7, 0.7, 0.7, 1.0 };
    }

    void Scene::OnMouseButtonReleasedForButton(Event* event, Entity* e)
    {
        auto c = e->GetComponent<Material2DComponent>(ComponentType_Material2D);
        c->Color = { 0.9, 0.8, 0.8, 1.0 };
    }

    void Scene::OnViewportResize(uint32_t x, uint32_t y, uint32_t width, uint32_t height)
    {
        //if (m_ViewportWidth == width && m_ViewportHeight == height)
        //    return;

        if (width == 0 || height == 0)
            return;

        m_ViewportWidth = width;
        m_ViewportHeight = height;

        Renderer2D::OnViewportResize(x, y, width, height);
        Renderer3D::OnViewportResize(x, y, width, height);

        if (m_OrthographicCamera)
        {
            m_OrthographicCamera->SetProjection(0.0, width, height, 0.0);
        }

        if (m_PerspectiveCamera)
        {
            m_PerspectiveCamera->SetAspect((float)width / (float)height);
        }
        if (m_EditPerspectiveCamera)
        {
            m_EditPerspectiveCamera->SetAspect((float)width / (float)height);
        }
    }

    Entity *Scene::GetPrimaryCameraEntity()
    {
        return NULL;
    }

    void Scene::Step(int frames)
    {
        m_StepFrames = frames;
    }

    Entity *Scene::DuplicateEntity(Entity *entity)
    {
        // Copy name because we're going to modify component data structure
        std::string name = entity->GetName();
        Entity *newEntity = CreateEntity(name);
        
        return newEntity;
    }

    Entity *Scene::FindEntityByNameRecursion(const std::string name, Entity *parent)
    {
        if (!parent)
            return nullptr;

        for (int i = 0; i < parent->GetChildCount(); i++)
        {
            Entity *p = parent->GetChild(i);
            if (name == p->GetComponent<TagComponent>(ComponentType_Tag)->Tag)
            {
                return p;
            }
            if (p->GetChildCount() > 0)
            {
                Entity *child = FindEntityByNameRecursion(name, p);
                if (child)
                    return child;
            }
        }
        return nullptr;
    }

    Entity * Scene::FindEntityByRigidBoyRecursion(const btRigidBody * body, Entity * parent)
    {
        if (!parent)
            return nullptr;

        for (int i = 0; i < parent->GetChildCount(); i++)
        {
            Entity *p = parent->GetChild(i);
            if (p->HasComponent(ComponentType_RigidBody)) {
                if (RigidBodyShapeType_Box == p->GetComponent<RigidBodyComponent>(ComponentType_RigidBody)->RigidBodyData.RigidBodyShapeTypeValue)
                {
                    if (body == (p->GetComponent<RigidBodyComponent>(ComponentType_RigidBody))->RigidBodyData.BtRigidBody)
                    {
                        return p;
                    }
                }
                else if (RigidBodyShapeType_TriangleMesh == p->GetComponent<RigidBodyComponent>(ComponentType_RigidBody)->RigidBodyData.RigidBodyShapeTypeValue)
                {
                    if (body == (p->GetComponent<RigidBodyComponent>(ComponentType_RigidBody)->RigidBodyData.BtRigidBodyes[0]))
                    {
                        return p;
                    }
                }                
            }
            
            if (p->GetChildCount() > 0)
            {
                Entity *child = FindEntityByRigidBoyRecursion(body, p);
                if (child)
                    return child;
            }
        }
        return nullptr;
    }

    void Scene::SetCurrentSelectEntity(Entity * e)
    {        
        m_CurrentSelectEntity = e;

        if (!m_ArrowGlobalAxisX) {// create
            m_ArrowGlobalAxisX = CreateArrowAxis(TagType_ArrowAxisX, glm::vec4(1.0, 0.0, 0.0, 1.0), glm::vec3(0.0), glm::vec3(4.0, 0.3, 0.3), glm::vec3(4.0, 0.0, 0.0));
        }

        if (!m_ArrowGlobalAxisY) {// create
            m_ArrowGlobalAxisY = CreateArrowAxis(TagType_ArrowAxisY, glm::vec4(0.0, 1.0, 0.0, 1.0), glm::vec3(0.0, 0.0, CCPI / 2.0), glm::vec3(0.3, 4.0, 0.3), glm::vec3(0.0, 4.0, 0.0));
        }

        if (!m_ArrowGlobalAxisZ) {// create
            m_ArrowGlobalAxisZ = CreateArrowAxis(TagType_ArrowAxisZ, glm::vec4(0.0, 0.0, 1.0, 1.0), glm::vec3(0.0, -CCPI / 2.0, 0.0), glm::vec3(0.3, 0.3, 4.0), glm::vec3(0.0, 0.0, 4.0));
        }

        if (m_CurrentSelectEntity) {
        }
        else {
            //hide
            TagComponent* tagX = m_ArrowGlobalAxisX->GetComponent<TagComponent>(ComponentType_Tag);
            tagX->Visible = false;

            TagComponent* tagY = m_ArrowGlobalAxisY->GetComponent<TagComponent>(ComponentType_Tag);
            tagY->Visible = false;

            TagComponent* tagZ = m_ArrowGlobalAxisZ->GetComponent<TagComponent>(ComponentType_Tag);
            tagZ->Visible = false;
        }
    }

    void Scene::SaveEntityRecursivelyEngine(Entity *parent, tinyxml2::XMLDocument &doc, tinyxml2::XMLElement &xml)
    {
        if (!parent)
            return;

        for (int i = 0; i < parent->GetChildCount(); i++)
        {

            Entity *p = parent->GetChild(i);
            if (!p)
                continue;

            bool hasLoadModel = false;

            tinyxml2::XMLElement *node_child = doc.NewElement("Node");

            node_child->SetAttribute("name", p->GetName().c_str());
            node_child->SetAttribute("uuid", Tool::uint64_t2Str(p->GetUUID()).c_str());

            if (p->HasComponent(ComponentType_Tag))
            {
                tinyxml2::XMLElement *e = doc.NewElement("TagComponent");

                auto c = p->GetComponent<TagComponent>(ComponentType_Tag);
                e->SetAttribute("Tag", c->Tag.c_str());

                if (TagType_Arrow == c->Type) {
                    continue;
                }

                node_child->InsertEndChild(e);
            }

            if (p->HasComponent(ComponentType_Transform))
            {
                tinyxml2::XMLElement *e = doc.NewElement("TransformComponent");

                auto c = p->GetComponent<TransformComponent>(ComponentType_Transform);
                e->SetAttribute("Translation.X", c->Translation[0]);
                e->SetAttribute("Translation.Y", c->Translation[1]);
                e->SetAttribute("Translation.Z", c->Translation[2]);
                e->SetAttribute("Rotation.X", c->Rotation[0]);
                e->SetAttribute("Rotation.Y", c->Rotation[1]);
                e->SetAttribute("Rotation.Z", c->Rotation[2]);
                e->SetAttribute("Scale.X", c->Scale[0]);
                e->SetAttribute("Scale.Y", c->Scale[1]);
                e->SetAttribute("Scale.Z", c->Scale[2]);

                node_child->InsertEndChild(e);
            }

            if (p->HasComponent(ComponentType_Light))
            {
                tinyxml2::XMLElement *e = doc.NewElement("LightComponent");

                auto c = p->GetComponent<LightComponent>(ComponentType_Light);
                e->SetAttribute("Color.R", c->Color[0]);
                e->SetAttribute("Color.G", c->Color[1]);
                e->SetAttribute("Color.B", c->Color[2]);
                e->SetAttribute("Color.A", c->Color[3]);

                e->SetAttribute("Position.X", c->Position[0]);
                e->SetAttribute("Position.Y", c->Position[1]);
                e->SetAttribute("Position.Z", c->Position[2]);
                e->SetAttribute("Position.W", c->Position[3]);

                node_child->InsertEndChild(e);
            }

            if (p->HasComponent(ComponentType_Camera))
            {
                tinyxml2::XMLElement *e = doc.NewElement("CameraComponent");

                auto c = p->GetComponent<CameraComponent>(ComponentType_Camera);
                e->SetAttribute("Primary", c->Primary);
                e->SetAttribute("Type2d", c->Type2d);
                e->SetAttribute("FixedAspectRatio", c->FixedAspectRatio);

                e->SetAttribute("Position.X", c->camera->GetPosition()[0]);
                e->SetAttribute("Position.Y", c->camera->GetPosition()[1]);
                e->SetAttribute("Position.Z", c->camera->GetPosition()[2]);

                if (c->Type2d)
                {
                }
                else
                {
                    e->SetAttribute("HasLookAt", ((PerspectiveCamera *)c->camera)->GetHasLookAt());
                    e->SetAttribute("fovy", ((PerspectiveCamera *)c->camera)->GetFovy());
                    e->SetAttribute("aspect", ((PerspectiveCamera *)c->camera)->GetAspect());
                    e->SetAttribute("yaw", ((PerspectiveCamera *)c->camera)->GetRotationYaw());
                    e->SetAttribute("pitch", ((PerspectiveCamera *)c->camera)->GetRotationPitch());

                    e->SetAttribute("TargetPosition.X", c->camera->GetTargetPosition()[0]);
                    e->SetAttribute("TargetPosition.Y", c->camera->GetTargetPosition()[1]);
                    e->SetAttribute("TargetPosition.Z", c->camera->GetTargetPosition()[2]);
                }

                node_child->InsertEndChild(e);
            }

            if (p->HasComponent(ComponentType_Material2D))
            {
                tinyxml2::XMLElement *e = doc.NewElement("Material2DComponent");

                auto c = p->GetComponent<Material2DComponent>(ComponentType_Material2D);
                e->SetAttribute("Color.R", c->Color[0]);
                e->SetAttribute("Color.G", c->Color[1]);
                e->SetAttribute("Color.B", c->Color[2]);
                e->SetAttribute("Color.A", c->Color[3]);
                e->SetAttribute("TilingFactor", c->TilingFactor);

                e->SetAttribute("Texture.Path", c->Texture ? c->Texture->GetPath().c_str() : "");

                node_child->InsertEndChild(e);
            }

            if (p->HasComponent(ComponentType_MeshBasicMaterial))
            {
                tinyxml2::XMLElement *e = doc.NewElement("MeshBasicMaterialComponent");

                auto c = p->GetComponent<MeshBasicMaterialComponent>(ComponentType_MeshBasicMaterial);
                e->SetAttribute("Color.R", c->Color[0]);
                e->SetAttribute("Color.G", c->Color[1]);
                e->SetAttribute("Color.B", c->Color[2]);
                e->SetAttribute("Color.A", c->Color[3]);
                e->SetAttribute("TilingFactor", c->TilingFactor);

                e->SetAttribute("Texture.Path", c->Texture ? c->Texture->GetPath().c_str() : "");

                node_child->InsertEndChild(e);
            }

            if (p->HasComponent(ComponentType_Font))
            {
                tinyxml2::XMLElement *e = doc.NewElement("FontComponent");

                auto c = p->GetComponent<FontComponent>(ComponentType_Font);
                e->SetAttribute("scale", c->scale);
                e->SetAttribute("fontSize", c->fontSize);
                e->SetAttribute("text", c->text.c_str());
                e->SetAttribute("fontName", c->font->name.c_str());
                e->SetAttribute("fontPath", c->font->path.c_str());

                node_child->InsertEndChild(e);
            }

            if (p->HasComponent(ComponentType_Model))
            {
                tinyxml2::XMLElement *e = doc.NewElement("ModelComponent");

                auto c = p->GetComponent<ModelComponent>(ComponentType_Model);
                e->SetAttribute("Path", c->Path.c_str());

                node_child->InsertEndChild(e);
                hasLoadModel = true;
            }

            if (p->HasComponent(ComponentType_Script))
            {
                tinyxml2::XMLElement *e = doc.NewElement("ScriptComponent");

                auto c = p->GetComponent<ScriptComponent>(ComponentType_Script);
                e->SetAttribute("ClassName", c->ClassName.c_str());
                e->SetAttribute("Path", c->Path.c_str());

                node_child->InsertEndChild(e);

                m_scriptData += "#include \"" + c->ClassName + ".cpp\" \n";
                m_scriptDataFunction += "if(c==\"" + c->ClassName + "\") return new " + c->ClassName + "(c);\\\n";
            }

            if (p->HasComponent(ComponentType_RigidBody))
            {
                tinyxml2::XMLElement *e = doc.NewElement("RigidBodyComponent");

                auto c = p->GetComponent<RigidBodyComponent>(ComponentType_RigidBody);
                e->SetAttribute("RigidBodyShapeTypeValue", c->RigidBodyData.RigidBodyShapeTypeValue);
                if (RigidBodyShapeType_Box == c->RigidBodyData.RigidBodyShapeTypeValue) {
                    e->SetAttribute("BoxHalfExtents.X", c->RigidBodyData.BoxHalfExtents[0]);
                    e->SetAttribute("BoxHalfExtents.Y", c->RigidBodyData.BoxHalfExtents[1]);
                    e->SetAttribute("BoxHalfExtents.Z", c->RigidBodyData.BoxHalfExtents[2]);
                }
                
                e->SetAttribute("Transform.X", c->RigidBodyData.Transform[0]);
                e->SetAttribute("Transform.Y", c->RigidBodyData.Transform[1]);
                e->SetAttribute("Transform.Z", c->RigidBodyData.Transform[2]);
                e->SetAttribute("Offset.X", c->RigidBodyData.Offset[0]);
                e->SetAttribute("Offset.Y", c->RigidBodyData.Offset[1]);
                e->SetAttribute("Offset.Z", c->RigidBodyData.Offset[2]);
                e->SetAttribute("Mass", c->RigidBodyData.Mass);

                node_child->InsertEndChild(e);
            }

            if (p->HasComponent(ComponentType_Animation))
            {
                tinyxml2::XMLElement *e = doc.NewElement("AnimationComponent");

                auto c = p->GetComponent<AnimationComponent>(ComponentType_Animation);
                e->SetAttribute("AnimationLoop", c->AnimationLoop);
                e->SetAttribute("AnimationMixTime", c->AnimationMixTime);
                e->SetAttribute("AnimationSpeed", c->AnimationSpeed);
                e->SetAttribute("CurrentAnimatioName", c->CurrentAnimatioName.c_str());

                std::string data;
                auto it = c->AnimationInfoData.AnimationInfoMap.begin();
                for (it; it != c->AnimationInfoData.AnimationInfoMap.end(); it++) {
                    data += (it->first + ":" + it->second->m_animationPath + ",");
                }
                e->SetAttribute("AnimList", data.c_str());

                node_child->InsertEndChild(e);
            }

            //if (p->HasComponent<MeshComponent>())
            //{
            //    tinyxml2::XMLElement *e = doc.NewElement("MeshComponent");

            //    auto &c = p->GetComponent<MeshComponent>();
            //    e->SetAttribute("Vertices", c.MeshData.SerializeVertex().c_str());
            //    e->SetAttribute("Indices", c.MeshData.SerializeIndices().c_str());
            //    //e->SetAttribute("Textures", c.MeshData.SerializeTextures().c_str());

            //    node_child->InsertEndChild(e);
            //}

            /*if (p->HasComponent<MeshModelMaterialComponent>())
            {
                tinyxml2::XMLElement *e = doc.NewElement("MeshModelMaterialComponent");

                auto &c = p->GetComponent<MeshModelMaterialComponent>();
                e->SetAttribute("HasColorMaterial", c.HasColorMaterial);
                e->SetAttribute("TilingFactor", c.TilingFactor);

                e->SetAttribute("Ambient.R", c.MaterialMeshType.Ambient[0]);
                e->SetAttribute("Ambient.G", c.MaterialMeshType.Ambient[1]);
                e->SetAttribute("Ambient.B", c.MaterialMeshType.Ambient[2]);
                e->SetAttribute("Ambient.A", c.MaterialMeshType.Ambient[3]);
                e->SetAttribute("Diffuse.R", c.MaterialMeshType.Diffuse[0]);
                e->SetAttribute("Diffuse.G", c.MaterialMeshType.Diffuse[1]);
                e->SetAttribute("Diffuse.B", c.MaterialMeshType.Diffuse[2]);
                e->SetAttribute("Diffuse.A", c.MaterialMeshType.Diffuse[3]);
                e->SetAttribute("Specular.R", c.MaterialMeshType.Specular[0]);
                e->SetAttribute("Specular.G", c.MaterialMeshType.Specular[1]);
                e->SetAttribute("Specular.B", c.MaterialMeshType.Specular[2]);
                e->SetAttribute("Specular.A", c.MaterialMeshType.Specular[3]);
                e->SetAttribute("Shininess", c.MaterialMeshType.Shininess);

                std::string data;
                int len = c.Textures.size();
                for (int i = 0; i < len; i++) {
                    data += c.Textures[i]->TypeName + "," + c.Textures[i]->GetPath() + ",";
                }
                e->SetAttribute("Textures", data.c_str());

                node_child->InsertEndChild(e);
            }*/

            // model trip save child
            if (!hasLoadModel && p->GetChildCount() > 0)
            {
                tinyxml2::XMLElement *node_child_child = doc.NewElement("Childs");
                SaveEntityRecursively(p, doc, *node_child_child);
                node_child->InsertEndChild(node_child_child);
            }

            xml.InsertEndChild(node_child);
        }
    }

    void Scene::AddEntityRecursivelyEngine(Entity *parent, tinyxml2::XMLElement &xml)
    {
        for (tinyxml2::XMLElement *node = xml.FirstChildElement(); node; node = node->NextSiblingElement())
        {
            if (!node->Name())
                continue;

            CC_CORE_INFO("AddEntityRecursively n=%s,v=%s\n ", node->Name(), node->FindAttribute("name")->Value());

            if (strcmp(node->Name(), "Node") == 0)
            {
                UUID uuid = Tool::Str2uint64_t(node->FindAttribute("uuid")->Value());
                std::string name = node->FindAttribute("name")->Value();

                Entity *e = CreateEntityWithUUID(uuid, name, parent);

                for (tinyxml2::XMLElement *node_child = node->FirstChildElement(); node_child; node_child = node_child->NextSiblingElement())
                {
                    if (strcmp(node_child->Name(), "TagComponent") == 0)
                    {
                        auto c = e->GetComponent<TagComponent>(ComponentType_Tag);
                        c->Tag = node_child->FindAttribute("Tag")->Value();
                    }
                    if (strcmp(node_child->Name(), "CameraComponent") == 0)
                    {

                        bool Primary, Type2d, FixedAspectRatio, HasLookAt;
                        tinyxml2::XMLUtil::ToBool(node_child->FindAttribute("Primary")->Value(), &Primary);
                        tinyxml2::XMLUtil::ToBool(node_child->FindAttribute("Type2d")->Value(), &Type2d);
                        tinyxml2::XMLUtil::ToBool(node_child->FindAttribute("FixedAspectRatio")->Value(), &FixedAspectRatio);                        

                        float PositionX, PositionY, PositionZ;
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Position.X")->Value(), &PositionX);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Position.Y")->Value(), &PositionY);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Position.Z")->Value(), &PositionZ);

                        if (Type2d)
                        {
                            if (!m_OrthographicCamera)
                            {
                                m_OrthographicCamera = new OrthographicCamera(0.0, m_ViewportWidth, m_ViewportHeight, 0.0);
                            }

                            m_OrthographicCamera->SetPosition({PositionX, PositionY, PositionZ});
                            CameraComponent* cameraComponent = new CameraComponent((Camera*)m_OrthographicCamera, Primary, Type2d, FixedAspectRatio);
                            e->AddOrReplaceComponent<CameraComponent>(cameraComponent);
                        }
                        else
                        {
                            float fovy, aspect, yaw, pitch;

                            tinyxml2::XMLUtil::ToBool(node_child->FindAttribute("HasLookAt")->Value(), &HasLookAt);

                            tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("fovy")->Value(), &fovy);
                            tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("aspect")->Value(), &aspect);
                            tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("yaw")->Value(), &yaw);
                            tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("pitch")->Value(), &pitch);

                            if (!m_PerspectiveCamera)
                            {
                                m_PerspectiveCamera = new PerspectiveCamera(fovy, aspect, 0.01, 1000.0);
                            }
                            if (!m_EditPerspectiveCamera)
                            {
                                m_EditPerspectiveCamera = new PerspectiveCamera(fovy, aspect, 0.01, 1000.0);
                            }

                            float TargetPositionX, TargetPositionY, TargetPositionZ;
                            tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("TargetPosition.X")->Value(), &TargetPositionX);
                            tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("TargetPosition.Y")->Value(), &TargetPositionY);
                            tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("TargetPosition.Z")->Value(), &TargetPositionZ);

                            m_PerspectiveCamera->SetPosition({PositionX, PositionY, PositionZ});                            
                            m_PerspectiveCamera->SetProjection(fovy, aspect, 0.01, 1000.0);
                            if (HasLookAt) {
                                m_PerspectiveCamera->SetTargetPosition({ TargetPositionX, TargetPositionY, TargetPositionZ });
                            }
                            else {
                                m_PerspectiveCamera->SetRotationYaw(yaw);
                                m_PerspectiveCamera->SetRotationPitch(pitch);
                            }                            
                            
                            CameraComponent* cameraComponent = new CameraComponent((Camera*)m_PerspectiveCamera, Primary, Type2d, FixedAspectRatio);
                            e->AddOrReplaceComponent<CameraComponent>(cameraComponent);

                            m_EditPerspectiveCamera->SetPosition({ PositionX, PositionY, PositionZ });                            
                            m_EditPerspectiveCamera->SetProjection(fovy, aspect, 0.01, 1000.0);
                         
                            if (HasLookAt) {
                                m_EditPerspectiveCamera->SetTargetPosition({ TargetPositionX, TargetPositionY, TargetPositionZ });
                            }
                            else {
                                m_EditPerspectiveCamera->SetRotationYaw(yaw);
                                m_EditPerspectiveCamera->SetRotationPitch(pitch);
                            }
                        }
                    }
                    if (strcmp(node_child->Name(), "TransformComponent") == 0)
                    {
                        auto c = e->GetComponent<TransformComponent>(ComponentType_Transform);

                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Translation.X")->Value(), &c->Translation[0]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Translation.Y")->Value(), &c->Translation[1]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Translation.Z")->Value(), &c->Translation[2]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Rotation.X")->Value(), &c->Rotation[0]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Rotation.Y")->Value(), &c->Rotation[1]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Rotation.Z")->Value(), &c->Rotation[2]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Scale.X")->Value(), &c->Scale[0]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Scale.Y")->Value(), &c->Scale[1]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Scale.Z")->Value(), &c->Scale[2]);
                    }
                    if (strcmp(node_child->Name(), "LightComponent") == 0)
                    {
                        LightComponent* lightComponent = new LightComponent(glm::vec4(1.0));

                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Color.R")->Value(), &lightComponent->Color[0]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Color.G")->Value(), &lightComponent->Color[1]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Color.B")->Value(), &lightComponent->Color[2]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Color.A")->Value(), &lightComponent->Color[3]);

                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Position.X")->Value(), &lightComponent->Position[0]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Position.y")->Value(), &lightComponent->Position[1]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Position.Z")->Value(), &lightComponent->Position[2]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Position.W")->Value(), &lightComponent->Position[3]);

                        SetLightColor(lightComponent->Color);
                        //SetLightPos((e->GetComponent<TransformComponent>(ComponentType_Transform))->Translation);
                        SetLightPos(lightComponent->Position);

                        e->AddOrReplaceComponent<LightComponent>(lightComponent);

                    }
                    if (strcmp(node_child->Name(), "Material2DComponent") == 0)
                    {
                        Material2DComponent* material2DComponent = new Material2DComponent();

                        std::string path = node_child->FindAttribute("Texture.Path")->Value();

                        if (!path.empty())
                        {
                            //material2DComponent->Texture = Texture2D::Create(path);
                            material2DComponent->Texture = CC::ResourceManager::LoadTexture(path.c_str(), path);
                        }

                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Color.R")->Value(), &material2DComponent->Color[0]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Color.G")->Value(), &material2DComponent->Color[1]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Color.B")->Value(), &material2DComponent->Color[2]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Color.A")->Value(), &material2DComponent->Color[3]);

                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("TilingFactor")->Value(), &material2DComponent->TilingFactor);

                        e->AddOrReplaceComponent<Material2DComponent>(material2DComponent);
                    }
                    if (strcmp(node_child->Name(), "MeshBasicMaterialComponent") == 0)
                    {
                        MeshBasicMaterialComponent* meshBasicMaterialComponent = new MeshBasicMaterialComponent();

                        std::string path = node_child->FindAttribute("Texture.Path")->Value();

                        if (!path.empty())
                        {
                            //meshBasicMaterialComponent->Texture = Texture2D::Create(path);
                            meshBasicMaterialComponent->Texture = CC::ResourceManager::LoadTexture(path.c_str(), path);
                        }

                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Color.R")->Value(), &meshBasicMaterialComponent->Color[0]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Color.G")->Value(), &meshBasicMaterialComponent->Color[1]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Color.B")->Value(), &meshBasicMaterialComponent->Color[2]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Color.A")->Value(), &meshBasicMaterialComponent->Color[3]);

                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("TilingFactor")->Value(), &meshBasicMaterialComponent->TilingFactor);
                        e->AddOrReplaceComponent<MeshBasicMaterialComponent>(meshBasicMaterialComponent);
                    }
                    if (strcmp(node_child->Name(), "FontComponent") == 0)
                    {
                        std::string fontName = node_child->FindAttribute("fontName")->Value();
                        std::string fontPath = node_child->FindAttribute("fontPath")->Value();

                        //not suport multi font
                        //Font *f = LoadFont(fontPath.c_str(), fontName);

                         FontComponent* fontComponent = new FontComponent(GetFont());

                        fontComponent->text = node_child->FindAttribute("text")->Value();

                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("scale")->Value(), &fontComponent->scale);
                        tinyxml2::XMLUtil::ToUnsigned(node_child->FindAttribute("fontSize")->Value(), &fontComponent->fontSize);
                        e->AddOrReplaceComponent<FontComponent>(fontComponent);

                    }
                    if (strcmp(node_child->Name(), "ModelComponent") == 0)
                    {
                        ModelComponent* modelComponent = new ModelComponent();

                        std::string path = node_child->FindAttribute("Path")->Value();

                        if (!path.empty())
                        {
                            modelComponent->Path = path;

                            Model* model = ResourceManager::LoadModel(modelComponent->Path.c_str(), "plane");
                            if (model) {
                                e->AddChildByMeshes(model->Meshes);
                                e->SetAnimationInfo(model->AnimationInfo);
                            }                          
                            
                        }
                        e->AddOrReplaceComponent<ModelComponent>(modelComponent);
                        CC_CORE_INFO("load ModelComponent=%s\n", path.c_str());
                    }
                    if (strcmp(node_child->Name(), "ScriptComponent") == 0)
                    {
                        
                        std::string className = node_child->FindAttribute("ClassName")->Value();
                        std::string path = node_child->FindAttribute("Path")->Value();

                        ScriptComponent* scriptComponent = new ScriptComponent(className, path);
                        e->AddOrReplaceComponent<ScriptComponent>(scriptComponent);

                    }
                    if (strcmp(node_child->Name(), "RigidBodyComponent") == 0)
                    {
                        glm::vec3 BoxHalfExtents, Transform, Rotation, Scale, Offset;
                        float Mass;
                        int shapeType;
                        tinyxml2::XMLUtil::ToInt(node_child->FindAttribute("RigidBodyShapeTypeValue")->Value(), &shapeType);                        
                        
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Transform.X")->Value(), &Transform[0]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Transform.Y")->Value(), &Transform[1]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Transform.Z")->Value(), &Transform[2]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Offset.X")->Value(), &Offset[0]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Offset.Y")->Value(), &Offset[1]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Offset.Z")->Value(), &Offset[2]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Rotation.X")->Value(), &Rotation[0]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Rotation.Y")->Value(), &Rotation[1]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Rotation.Z")->Value(), &Rotation[2]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Scale.X")->Value(), &Scale[0]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Scale.Y")->Value(), &Scale[1]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Scale.Z")->Value(), &Scale[2]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Mass")->Value(), &Mass);

                        if (RigidBodyShapeType_Box == (RigidBodyShapeType)shapeType) {
                            tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("BoxHalfExtents.X")->Value(), &BoxHalfExtents[0]);
                            tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("BoxHalfExtents.Y")->Value(), &BoxHalfExtents[1]);
                            tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("BoxHalfExtents.Z")->Value(), &BoxHalfExtents[2]);

                            RigidBody _RigidBody = Physics::CreateShapeBox(BoxHalfExtents[0], BoxHalfExtents[1], BoxHalfExtents[2], Mass, Transform, Offset);

                            RigidBodyComponent* rigidBodyComponent = new RigidBodyComponent(_RigidBody);
                            e->AddOrReplaceComponent<RigidBodyComponent>(rigidBodyComponent);
                        }
                        else if (RigidBodyShapeType_TriangleMesh == (RigidBodyShapeType)shapeType) {
                            AddRigidBodyComponent(e, RigidBodyShapeType_TriangleMesh, Transform, Rotation, Scale, Offset, Mass);
                            //auto& c = *(RigidBodyComponent*)e->GetComponent<RigidBodyComponent>(ComponentType_RigidBody);
                            //c.RigidBodyData.Offset = Offset;
                            //c.RigidBodyData.Mass = Mass;
                            //c.RigidBodyData.Transform = Transform;
                        }                        
                    }
                    if (strcmp(node_child->Name(), "AnimationComponent") == 0)
                    {
                        bool AnimationLoop;
                        double AnimationMixTime, AnimationSpeed;
                        tinyxml2::XMLUtil::ToBool(node_child->FindAttribute("AnimationLoop")->Value(), &AnimationLoop);

                        tinyxml2::XMLUtil::ToDouble(node_child->FindAttribute("AnimationMixTime")->Value(), &AnimationMixTime);
                        tinyxml2::XMLUtil::ToDouble(node_child->FindAttribute("AnimationSpeed")->Value(), &AnimationSpeed);

                        std::string CurrentAnimatioName = node_child->FindAttribute("CurrentAnimatioName")->Value();

                        AnimationComponent* animationComponent = new AnimationComponent(e->GetAnimationInfo());

                        animationComponent->AnimationLoop = AnimationLoop;
                        animationComponent->AnimationMixTime = AnimationMixTime;
                        animationComponent->AnimationSpeed = AnimationSpeed;

                        std::string AnimList = node_child->FindAttribute("AnimList")->Value();

                        std::stringstream ss(AnimList);
                        std::string item;

                        while (std::getline(ss, item, ',')) {
                            if (!item.empty()) {
                                int index = item.find(":");
                                if (index != -1) {
                                    std::string name = item.substr(0, index);
                                    std::string path = item.substr(index + 1, item.size());
                                    animationComponent->AddAnimation(name, path);
                                    CC_CORE_INFO("load AnimationComponent %s %s\n", name.c_str(), path.c_str());
                                }
                            }
                        }

                        animationComponent->PlayAnimation(CurrentAnimatioName, AnimationLoop);
                        e->AddOrReplaceComponent<AnimationComponent>(animationComponent);
                    }

                    //if (strcmp(node_child->Name(), "MeshComponent") == 0)
                    //{
                    //    Mesh MeshData;                        

                    //    std::string Vertices = node_child->FindAttribute("Vertices")->Value();
                    //    std::string Indices = node_child->FindAttribute("Indices")->Value();
                    //    //std::string Textures = node_child->FindAttribute("Textures")->Value();

                    //    MeshData.ParseVertex(Vertices);
                    //    MeshData.ParseIndices(Indices);
                    //    //c.MeshData.ParseTextures(Textures);

                    //    auto &c = e->AddComponent<MeshComponent>(MeshData);
                    //}

                    //if (strcmp(node_child->Name(), "MeshModelMaterialComponent") == 0)
                    //{
                    //    bool HasColorMaterial;
                    //    float TilingFactor, Shininess;
                    //    float Ambient_R,Ambient_G,Ambient_B,Ambient_A;
                    //    float Diffuse_R,Diffuse_G,Diffuse_B,Diffuse_A;
                    //    float Specular_R,Specular_G,Specular_B,Specular_A;

                    //    tinyxml2::XMLUtil::ToBool(node_child->FindAttribute("HasColorMaterial")->Value(), &HasColorMaterial);
                    //    tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("TilingFactor")->Value(), &TilingFactor);

                    //    tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Ambient.R")->Value(), &Ambient_R);
                    //    tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Ambient.G")->Value(), &Ambient_G);
                    //    tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Ambient.B")->Value(), &Ambient_B);
                    //    tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Ambient.A")->Value(), &Ambient_A);

                    //    tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Diffuse.R")->Value(), &Diffuse_R);
                    //    tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Diffuse.G")->Value(), &Diffuse_G);
                    //    tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Diffuse.B")->Value(), &Diffuse_B);
                    //    tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Diffuse.A")->Value(), &Diffuse_A);

                    //    tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Specular.R")->Value(), &Specular_R);
                    //    tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Specular.G")->Value(), &Specular_G);
                    //    tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Specular.B")->Value(), &Specular_B);
                    //    tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Specular.A")->Value(), &Specular_A);

                    //    tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Shininess")->Value(), &Shininess);

                    //    std::string TexturesStr = node_child->FindAttribute("Textures")->Value();

                    //    std::stringstream ss(TexturesStr);
                    //    std::string item;

                    //    std::vector<std::string> array;
                    //    while (std::getline(ss, item, ',')) {
                    //        if (!item.empty()) {
                    //            array.push_back(item);
                    //        }
                    //    }

                    //    std::vector<Texture2D *> Textures;
                    //    for (int i = 0; i < array.size() - 1; i+=1) {
                    //        std::string type = array[i];
                    //        std::string path = array[i+1];
                    //        if (!path.empty())
                    //        {
                    //            Texture2D *t = Texture2D::Create(path);
                    //            t->TypeName = type;
                    //            Textures.push_back(t);
                    //        }
                    //    }

                    //    MaterialMesh MaterialMeshType;
                    //    MaterialMeshType.Ambient = { Ambient_R, Ambient_G, Ambient_B, Ambient_A };
                    //    MaterialMeshType.Diffuse = { Diffuse_R, Diffuse_G, Diffuse_B, Diffuse_A };
                    //    MaterialMeshType.Specular = { Specular_R, Specular_G, Specular_B, Specular_A };
                    //    MaterialMeshType.Shininess = Shininess;
                    //    
                    //    auto &c = e->AddComponent<MeshModelMaterialComponent>(HasColorMaterial, MaterialMeshType, Textures, TilingFactor);
                    //}

                    if (strcmp(node_child->Name(), "Childs") == 0)
                    {
                        AddEntityRecursively(e, *node_child);
                    }
                }
            }
        }
    }

    void Scene::SaveEntityRecursively(Entity *parent, tinyxml2::XMLDocument &doc, tinyxml2::XMLElement &xml)
    {
        if (!parent)
            return;

        for (int i = 0; i < parent->GetChildCount(); i++)
        {

            Entity *p = parent->GetChild(i);
            if (!p)
                continue;

            std::string tag = p->GetComponent<TagComponent>(ComponentType_Tag)->Tag;
            if ("camera2d" == tag || "camera3d" == tag || "Light" == tag
                || "wall_front" == tag || "wall_back" == tag || "wall_bottom" == tag || "wall_top" == tag || "wall_left" == tag || "wall_right" == tag
                || "helptip" == tag) {
                continue;
            }

            bool hasLoadModel = false;

            tinyxml2::XMLElement *node_child = doc.NewElement("Node");

            node_child->SetAttribute("name", p->GetName().c_str());
            node_child->SetAttribute("uuid", Tool::uint64_t2Str(p->GetUUID()).c_str());

            if (p->HasComponent(ComponentType_Tag))
            {
                tinyxml2::XMLElement *e = doc.NewElement("TagComponent");

                auto c = p->GetComponent<TagComponent>(ComponentType_Tag);
                e->SetAttribute("Tag", c->Tag.c_str());
                e->SetAttribute("Type", c->Type);
                e->SetAttribute("SubType", c->SubType);

                if (TagType_Arrow == c->Type) {
                    continue;
                }

                node_child->InsertEndChild(e);
            }

            if (p->HasComponent(ComponentType_Transform))
            {
                tinyxml2::XMLElement *e = doc.NewElement("TransformComponent");

                auto c = p->GetComponent<TransformComponent>(ComponentType_Transform);
                e->SetAttribute("Translation.X", c->Translation[0]);
                e->SetAttribute("Translation.Y", c->Translation[1]);
                e->SetAttribute("Translation.Z", c->Translation[2]);
                e->SetAttribute("Rotation.X", c->Rotation[0]);
                e->SetAttribute("Rotation.Y", c->Rotation[1]);
                e->SetAttribute("Rotation.Z", c->Rotation[2]);
                e->SetAttribute("Scale.X", c->Scale[0]);
                e->SetAttribute("Scale.Y", c->Scale[1]);
                e->SetAttribute("Scale.Z", c->Scale[2]);

                node_child->InsertEndChild(e);
            }

            if (p->HasComponent(ComponentType_Light))
            {
                tinyxml2::XMLElement *e = doc.NewElement("LightComponent");

                auto c = p->GetComponent<LightComponent>(ComponentType_Light);
                e->SetAttribute("Color.R", c->Color[0]);
                e->SetAttribute("Color.G", c->Color[1]);
                e->SetAttribute("Color.B", c->Color[2]);
                e->SetAttribute("Color.A", c->Color[3]);

                e->SetAttribute("Position.X", c->Position[0]);
                e->SetAttribute("Position.Y", c->Position[1]);
                e->SetAttribute("Position.Z", c->Position[2]);
                e->SetAttribute("Position.W", c->Position[3]);

                node_child->InsertEndChild(e);
            }

            if (p->HasComponent(ComponentType_Camera))
            {
                tinyxml2::XMLElement *e = doc.NewElement("CameraComponent");

                auto c = p->GetComponent<CameraComponent>(ComponentType_Camera);
                e->SetAttribute("Primary", c->Primary);
                e->SetAttribute("Type2d", c->Type2d);
                e->SetAttribute("FixedAspectRatio", c->FixedAspectRatio);

                e->SetAttribute("Position.X", c->camera->GetPosition()[0]);
                e->SetAttribute("Position.Y", c->camera->GetPosition()[1]);
                e->SetAttribute("Position.Z", c->camera->GetPosition()[2]);

                if (c->Type2d)
                {
                }
                else
                {
                    e->SetAttribute("HasLookAt", ((PerspectiveCamera *)c->camera)->GetHasLookAt());
                    e->SetAttribute("fovy", ((PerspectiveCamera *)c->camera)->GetFovy());
                    e->SetAttribute("aspect", ((PerspectiveCamera *)c->camera)->GetAspect());
                    e->SetAttribute("yaw", ((PerspectiveCamera *)c->camera)->GetRotationYaw());
                    e->SetAttribute("pitch", ((PerspectiveCamera *)c->camera)->GetRotationPitch());

                    e->SetAttribute("TargetPosition.X", c->camera->GetTargetPosition()[0]);
                    e->SetAttribute("TargetPosition.Y", c->camera->GetTargetPosition()[1]);
                    e->SetAttribute("TargetPosition.Z", c->camera->GetTargetPosition()[2]);
                }

                node_child->InsertEndChild(e);
            }

            if (p->HasComponent(ComponentType_Material2D))
            {
                tinyxml2::XMLElement *e = doc.NewElement("Material2DComponent");

                auto c = p->GetComponent<Material2DComponent>(ComponentType_Material2D);
                e->SetAttribute("Color.R", c->Color[0]);
                e->SetAttribute("Color.G", c->Color[1]);
                e->SetAttribute("Color.B", c->Color[2]);
                e->SetAttribute("Color.A", c->Color[3]);
                e->SetAttribute("TilingFactor", c->TilingFactor);

                e->SetAttribute("Texture.Path", c->Texture ? c->Texture->GetPath().c_str() : "");

                node_child->InsertEndChild(e);
            }

            if (p->HasComponent(ComponentType_MeshBasicMaterial))
            {
                tinyxml2::XMLElement *e = doc.NewElement("MeshBasicMaterialComponent");

                auto c = p->GetComponent<MeshBasicMaterialComponent>(ComponentType_MeshBasicMaterial);
                e->SetAttribute("Color.R", c->Color[0]);
                e->SetAttribute("Color.G", c->Color[1]);
                e->SetAttribute("Color.B", c->Color[2]);
                e->SetAttribute("Color.A", c->Color[3]);
                e->SetAttribute("TilingFactor", c->TilingFactor);

                e->SetAttribute("Texture.Path", c->Texture ? c->Texture->GetPath().c_str() : "");

                node_child->InsertEndChild(e);
            }

            if (p->HasComponent(ComponentType_Font))
            {
                tinyxml2::XMLElement *e = doc.NewElement("FontComponent");

                auto c = p->GetComponent<FontComponent>(ComponentType_Font);
                e->SetAttribute("scale", c->scale);
                e->SetAttribute("fontSize", c->fontSize);
                e->SetAttribute("text", c->text.c_str());
                e->SetAttribute("fontName", c->font->name.c_str());
                e->SetAttribute("fontPath", c->font->path.c_str());

                node_child->InsertEndChild(e);
            }

            if (p->HasComponent(ComponentType_Model))
            {
                tinyxml2::XMLElement *e = doc.NewElement("ModelComponent");

                auto c = p->GetComponent<ModelComponent>(ComponentType_Model);
                e->SetAttribute("Path", c->Path.c_str());

                node_child->InsertEndChild(e);
                hasLoadModel = true;
            }

            if (p->HasComponent(ComponentType_Script))
            {
                tinyxml2::XMLElement *e = doc.NewElement("ScriptComponent");

                auto c = p->GetComponent<ScriptComponent>(ComponentType_Script);
                e->SetAttribute("ClassName", c->ClassName.c_str());
                e->SetAttribute("Path", c->Path.c_str());

                node_child->InsertEndChild(e);

                m_scriptData += "#include \"" + c->ClassName + ".cpp\" \n";
                m_scriptDataFunction += "if(c==\"" + c->ClassName + "\") return new " + c->ClassName + "(c);\\\n";
            }

            if (p->HasComponent(ComponentType_RigidBody))
            {
                tinyxml2::XMLElement *e = doc.NewElement("RigidBodyComponent");

                auto c = p->GetComponent<RigidBodyComponent>(ComponentType_RigidBody);
                e->SetAttribute("RigidBodyShapeTypeValue", c->RigidBodyData.RigidBodyShapeTypeValue);
                if (RigidBodyShapeType_Box == c->RigidBodyData.RigidBodyShapeTypeValue) {
                    e->SetAttribute("BoxHalfExtents.X", c->RigidBodyData.BoxHalfExtents[0]);
                    e->SetAttribute("BoxHalfExtents.Y", c->RigidBodyData.BoxHalfExtents[1]);
                    e->SetAttribute("BoxHalfExtents.Z", c->RigidBodyData.BoxHalfExtents[2]);
                }

                e->SetAttribute("Transform.X", c->RigidBodyData.Transform[0]);
                e->SetAttribute("Transform.Y", c->RigidBodyData.Transform[1]);
                e->SetAttribute("Transform.Z", c->RigidBodyData.Transform[2]);
                e->SetAttribute("Rotation.X", c->RigidBodyData.Rotation[0]);
                e->SetAttribute("Rotation.Y", c->RigidBodyData.Rotation[1]);
                e->SetAttribute("Rotation.Z", c->RigidBodyData.Rotation[2]);
                e->SetAttribute("Scale.X", c->RigidBodyData.Scale[0]);
                e->SetAttribute("Scale.Y", c->RigidBodyData.Scale[1]);
                e->SetAttribute("Scale.Z", c->RigidBodyData.Scale[2]);
                e->SetAttribute("Offset.X", c->RigidBodyData.Offset[0]);
                e->SetAttribute("Offset.Y", c->RigidBodyData.Offset[1]);
                e->SetAttribute("Offset.Z", c->RigidBodyData.Offset[2]);
                e->SetAttribute("Mass", c->RigidBodyData.Mass);

                node_child->InsertEndChild(e);
            }

            if (p->HasComponent(ComponentType_Animation))
            {
                tinyxml2::XMLElement *e = doc.NewElement("AnimationComponent");

                auto c = p->GetComponent<AnimationComponent>(ComponentType_Animation);
                e->SetAttribute("AnimationLoop", c->AnimationLoop);
                e->SetAttribute("AnimationMixTime", c->AnimationMixTime);
                e->SetAttribute("AnimationSpeed", c->AnimationSpeed);
                e->SetAttribute("CurrentAnimatioName", c->CurrentAnimatioName.c_str());

                std::string data;
                auto it = c->AnimationInfoData.AnimationInfoMap.begin();
                for (it; it != c->AnimationInfoData.AnimationInfoMap.end(); it++) {
                    data += (it->first + ":" + it->second->m_animationPath + ",");
                }
                e->SetAttribute("AnimList", data.c_str());

                node_child->InsertEndChild(e);
            }

            //if (p->HasComponent<MeshComponent>())
            //{
            //    tinyxml2::XMLElement *e = doc.NewElement("MeshComponent");

            //    auto &c = p->GetComponent<MeshComponent>();
            //    e->SetAttribute("Vertices", c.MeshData.SerializeVertex().c_str());
            //    e->SetAttribute("Indices", c.MeshData.SerializeIndices().c_str());
            //    //e->SetAttribute("Textures", c.MeshData.SerializeTextures().c_str());

            //    node_child->InsertEndChild(e);
            //}

            /*if (p->HasComponent<MeshModelMaterialComponent>())
            {
                tinyxml2::XMLElement *e = doc.NewElement("MeshModelMaterialComponent");

                auto &c = p->GetComponent<MeshModelMaterialComponent>();
                e->SetAttribute("HasColorMaterial", c.HasColorMaterial);
                e->SetAttribute("TilingFactor", c.TilingFactor);

                e->SetAttribute("Ambient.R", c.MaterialMeshType.Ambient[0]);
                e->SetAttribute("Ambient.G", c.MaterialMeshType.Ambient[1]);
                e->SetAttribute("Ambient.B", c.MaterialMeshType.Ambient[2]);
                e->SetAttribute("Ambient.A", c.MaterialMeshType.Ambient[3]);
                e->SetAttribute("Diffuse.R", c.MaterialMeshType.Diffuse[0]);
                e->SetAttribute("Diffuse.G", c.MaterialMeshType.Diffuse[1]);
                e->SetAttribute("Diffuse.B", c.MaterialMeshType.Diffuse[2]);
                e->SetAttribute("Diffuse.A", c.MaterialMeshType.Diffuse[3]);
                e->SetAttribute("Specular.R", c.MaterialMeshType.Specular[0]);
                e->SetAttribute("Specular.G", c.MaterialMeshType.Specular[1]);
                e->SetAttribute("Specular.B", c.MaterialMeshType.Specular[2]);
                e->SetAttribute("Specular.A", c.MaterialMeshType.Specular[3]);
                e->SetAttribute("Shininess", c.MaterialMeshType.Shininess);

                std::string data;
                int len = c.Textures.size();
                for (int i = 0; i < len; i++) {
                    data += c.Textures[i]->TypeName + "," + c.Textures[i]->GetPath() + ",";
                }
                e->SetAttribute("Textures", data.c_str());

                node_child->InsertEndChild(e);
            }*/

            // model trip save child
            if (!hasLoadModel && p->GetChildCount() > 0)
            {
                tinyxml2::XMLElement *node_child_child = doc.NewElement("Childs");
                SaveEntityRecursively(p, doc, *node_child_child);
                node_child->InsertEndChild(node_child_child);
            }

            xml.InsertEndChild(node_child);
        }
    }

    void Scene::AddEntityRecursively(Entity *parent, tinyxml2::XMLElement &xml)
    {
        for (tinyxml2::XMLElement *node = xml.FirstChildElement(); node; node = node->NextSiblingElement())
        {
            if (!node->Name())
                continue;

            CC_CORE_INFO("AddEntityRecursively n=%s,v=%s\n ", node->Name(), node->FindAttribute("name")->Value());

            if (strcmp(node->Name(), "Node") == 0)
            {
                UUID uuid = Tool::Str2uint64_t(node->FindAttribute("uuid")->Value());
                std::string name = node->FindAttribute("name")->Value();

                Entity *e = CreateEntityWithUUID(uuid, name, parent);

                DesktopIconInfo desktopIconInfo;
                PhotoIconInfo photoIconInfo;
                VideoInfo videoInfo;

                for (tinyxml2::XMLElement *node_child = node->FirstChildElement(); node_child; node_child = node_child->NextSiblingElement())
                {
                    if (strcmp(node_child->Name(), "TagComponent") == 0)
                    {
                        auto c = e->GetComponent<TagComponent>(ComponentType_Tag);
                        c->Tag = node_child->FindAttribute("Tag")->Value();

                        int type, subtype;
                        tinyxml2::XMLUtil::ToInt(node_child->FindAttribute("Type")->Value(), &type);
                        tinyxml2::XMLUtil::ToInt(node_child->FindAttribute("SubType")->Value(), &subtype);
                        c->Type = (TagType)type;
                        c->SubType = (TagType)subtype;

                        bool need_delete_icon = false;
                        bool need_delete_video = false;
                        bool need_delete_photo = false;
                        if (TagType_DragMoveIcon == c->Type) {
                            for (int d = 0; d < m_DesktopIconInfos.size(); d++) {
                                if(c->Tag == m_DesktopIconInfos[d].name) {
                                    m_DesktopIconInfos[d].hasExistObj = e;
                                    desktopIconInfo = m_DesktopIconInfos[d];
                                    break;
                                }
                                if (d == m_DesktopIconInfos.size() - 1) {
                                    need_delete_icon = true;
                                }
                            }
                            if (need_delete_icon) {
                                DestroyEntity(e);
                                break;
                            }
                        }
                        else if (TagType_DragMoveStaticVideo == c->Type) {
                            for (int d = 0; d < m_VideoInfos.size(); d++) {
                                if (c->Tag == m_VideoInfos[d].name) {
                                    m_VideoInfos[d].hasExistObj = e;
                                    videoInfo = m_VideoInfos[d];
                                    break;
                                }
                                if (d == m_VideoInfos.size() - 1) {
                                    need_delete_video = true;
                                }
                            }
                            if (need_delete_video) {
                                DestroyEntity(e);
                                break;
                            }
                        }
                        else if (TagType_DragMoveStatic == c->Type) {
                            for (int d = 0; d < m_PhotoIconInfos.size(); d++) {
                                if (c->Tag == m_PhotoIconInfos[d].name) {
                                    m_PhotoIconInfos[d].hasExistObj = e;
                                    photoIconInfo = m_PhotoIconInfos[d];
                                    break;
                                }
                                if (d == m_PhotoIconInfos.size() - 1) {
                                    need_delete_photo = true;
                                }
                            }
                            if (need_delete_photo) {
                                DestroyEntity(e);
                                break;
                            }
                        }
                    }
                    if (strcmp(node_child->Name(), "CameraComponent") == 0)
                    {

                        bool Primary, Type2d, FixedAspectRatio, HasLookAt;
                        tinyxml2::XMLUtil::ToBool(node_child->FindAttribute("Primary")->Value(), &Primary);
                        tinyxml2::XMLUtil::ToBool(node_child->FindAttribute("Type2d")->Value(), &Type2d);
                        tinyxml2::XMLUtil::ToBool(node_child->FindAttribute("FixedAspectRatio")->Value(), &FixedAspectRatio);

                        float PositionX, PositionY, PositionZ;
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Position.X")->Value(), &PositionX);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Position.Y")->Value(), &PositionY);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Position.Z")->Value(), &PositionZ);

                        if (Type2d)
                        {
                            if (!m_OrthographicCamera)
                            {
                                m_OrthographicCamera = new OrthographicCamera(0.0, m_ViewportWidth, m_ViewportHeight, 0.0);
                            }

                            m_OrthographicCamera->SetPosition({ PositionX, PositionY, PositionZ });
                            CameraComponent* cameraComponent = new CameraComponent((Camera*)m_OrthographicCamera, Primary, Type2d, FixedAspectRatio);
                            e->AddOrReplaceComponent<CameraComponent>(cameraComponent);
                        }
                        else
                        {
                            float fovy, aspect, yaw, pitch;

                            tinyxml2::XMLUtil::ToBool(node_child->FindAttribute("HasLookAt")->Value(), &HasLookAt);

                            tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("fovy")->Value(), &fovy);
                            tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("aspect")->Value(), &aspect);
                            tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("yaw")->Value(), &yaw);
                            tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("pitch")->Value(), &pitch);

                            if (!m_PerspectiveCamera)
                            {
                                m_PerspectiveCamera = new PerspectiveCamera(fovy, aspect, 0.01, 1000.0);
                            }
                            if (!m_EditPerspectiveCamera)
                            {
                                m_EditPerspectiveCamera = new PerspectiveCamera(fovy, aspect, 0.01, 1000.0);
                            }

                            float TargetPositionX, TargetPositionY, TargetPositionZ;
                            tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("TargetPosition.X")->Value(), &TargetPositionX);
                            tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("TargetPosition.Y")->Value(), &TargetPositionY);
                            tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("TargetPosition.Z")->Value(), &TargetPositionZ);

                            m_PerspectiveCamera->SetPosition({ PositionX, PositionY, PositionZ });
                            m_PerspectiveCamera->SetProjection(fovy, aspect, 0.01, 1000.0);
                            if (HasLookAt) {
                                m_PerspectiveCamera->SetTargetPosition({ TargetPositionX, TargetPositionY, TargetPositionZ });
                            }
                            else {
                                m_PerspectiveCamera->SetRotationYaw(yaw);
                                m_PerspectiveCamera->SetRotationPitch(pitch);
                            }

                            CameraComponent* cameraComponent = new CameraComponent((Camera*)m_PerspectiveCamera, Primary, Type2d, FixedAspectRatio);
                            e->AddOrReplaceComponent<CameraComponent>(cameraComponent);

                            m_EditPerspectiveCamera->SetPosition({ PositionX, PositionY, PositionZ });
                            m_EditPerspectiveCamera->SetProjection(fovy, aspect, 0.01, 1000.0);

                            if (HasLookAt) {
                                m_EditPerspectiveCamera->SetTargetPosition({ TargetPositionX, TargetPositionY, TargetPositionZ });
                            }
                            else {
                                m_EditPerspectiveCamera->SetRotationYaw(yaw);
                                m_EditPerspectiveCamera->SetRotationPitch(pitch);
                            }
                        }
                    }
                    if (strcmp(node_child->Name(), "TransformComponent") == 0)
                    {
                        auto c = e->GetComponent<TransformComponent>(ComponentType_Transform);

                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Translation.X")->Value(), &c->Translation[0]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Translation.Y")->Value(), &c->Translation[1]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Translation.Z")->Value(), &c->Translation[2]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Rotation.X")->Value(), &c->Rotation[0]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Rotation.Y")->Value(), &c->Rotation[1]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Rotation.Z")->Value(), &c->Rotation[2]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Scale.X")->Value(), &c->Scale[0]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Scale.Y")->Value(), &c->Scale[1]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Scale.Z")->Value(), &c->Scale[2]);
                    }
                    if (strcmp(node_child->Name(), "LightComponent") == 0)
                    {
                        LightComponent* lightComponent = new LightComponent(glm::vec4(1.0));

                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Color.R")->Value(), &lightComponent->Color[0]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Color.G")->Value(), &lightComponent->Color[1]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Color.B")->Value(), &lightComponent->Color[2]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Color.A")->Value(), &lightComponent->Color[3]);

                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Position.X")->Value(), &lightComponent->Position[0]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Position.y")->Value(), &lightComponent->Position[1]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Position.Z")->Value(), &lightComponent->Position[2]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Position.W")->Value(), &lightComponent->Position[3]);

                        SetLightColor(lightComponent->Color);
                        //SetLightPos((e->GetComponent<TransformComponent>(ComponentType_Transform))->Translation);
                        SetLightPos(lightComponent->Position);

                        e->AddOrReplaceComponent<LightComponent>(lightComponent);

                    }
                    if (strcmp(node_child->Name(), "Material2DComponent") == 0)
                    {
                        Material2DComponent* material2DComponent = new Material2DComponent();

                        std::string path = node_child->FindAttribute("Texture.Path")->Value();

                        if (!path.empty())
                        {
                            //material2DComponent->Texture = Texture2D::Create(path);
                            material2DComponent->Texture = CC::ResourceManager::LoadTexture(path.c_str(), path);
                        }

                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Color.R")->Value(), &material2DComponent->Color[0]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Color.G")->Value(), &material2DComponent->Color[1]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Color.B")->Value(), &material2DComponent->Color[2]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Color.A")->Value(), &material2DComponent->Color[3]);

                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("TilingFactor")->Value(), &material2DComponent->TilingFactor);

                        e->AddOrReplaceComponent<Material2DComponent>(material2DComponent);
                    }
                    if (strcmp(node_child->Name(), "MeshBasicMaterialComponent") == 0)
                    {
                        MeshBasicMaterialComponent* meshBasicMaterialComponent = new MeshBasicMaterialComponent();

                        std::string path = node_child->FindAttribute("Texture.Path")->Value();

                        if (!path.empty())
                        {
                            //meshBasicMaterialComponent->Texture = Texture2D::Create(path);
                            meshBasicMaterialComponent->Texture = CC::ResourceManager::LoadTexture(path.c_str(), path);
                        }

                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Color.R")->Value(), &meshBasicMaterialComponent->Color[0]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Color.G")->Value(), &meshBasicMaterialComponent->Color[1]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Color.B")->Value(), &meshBasicMaterialComponent->Color[2]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Color.A")->Value(), &meshBasicMaterialComponent->Color[3]);

                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("TilingFactor")->Value(), &meshBasicMaterialComponent->TilingFactor);
                        e->AddOrReplaceComponent<MeshBasicMaterialComponent>(meshBasicMaterialComponent);
                    }
                    if (strcmp(node_child->Name(), "FontComponent") == 0)
                    {
                        std::string fontName = node_child->FindAttribute("fontName")->Value();
                        std::string fontPath = node_child->FindAttribute("fontPath")->Value();

                        //not suport multi font
                        //Font *f = LoadFont(fontPath.c_str(), fontName);

                        FontComponent* fontComponent = new FontComponent(GetFont());

                        fontComponent->text = node_child->FindAttribute("text")->Value();

                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("scale")->Value(), &fontComponent->scale);
                        tinyxml2::XMLUtil::ToUnsigned(node_child->FindAttribute("fontSize")->Value(), &fontComponent->fontSize);
                        e->AddOrReplaceComponent<FontComponent>(fontComponent);

                    }
                    if (strcmp(node_child->Name(), "ModelComponent") == 0)
                    {
                        ModelComponent* modelComponent = new ModelComponent();

                        std::string path = node_child->FindAttribute("Path")->Value();

                        if (!path.empty())
                        {
                            modelComponent->Path = path;

                            Model* model = ResourceManager::LoadModel(modelComponent->Path.c_str(), e->GetComponent<TagComponent>(ComponentType_Tag)->Tag);
                            if (model) {
                                e->AddChildByMeshes(model->Meshes);
                                e->SetAnimationInfo(model->AnimationInfo);
                            }

                        }
                        e->AddOrReplaceComponent<ModelComponent>(modelComponent);
                        CC_CORE_INFO("load ModelComponent=%s\n", path.c_str());
                    }
                    if (strcmp(node_child->Name(), "ScriptComponent") == 0)
                    {

                        std::string className = node_child->FindAttribute("ClassName")->Value();
                        std::string path = node_child->FindAttribute("Path")->Value();

                        ScriptComponent* scriptComponent = new ScriptComponent(className, path);
                        e->AddOrReplaceComponent<ScriptComponent>(scriptComponent);

                    }
                    if (strcmp(node_child->Name(), "RigidBodyComponent") == 0)
                    {
                        glm::vec3 BoxHalfExtents, Transform, Rotation, Scale, Offset;
                        float Mass;
                        int shapeType;
                        tinyxml2::XMLUtil::ToInt(node_child->FindAttribute("RigidBodyShapeTypeValue")->Value(), &shapeType);

                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Transform.X")->Value(), &Transform[0]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Transform.Y")->Value(), &Transform[1]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Transform.Z")->Value(), &Transform[2]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Rotation.X")->Value(), &Rotation[0]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Rotation.Y")->Value(), &Rotation[1]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Rotation.Z")->Value(), &Rotation[2]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Scale.X")->Value(), &Scale[0]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Scale.Y")->Value(), &Scale[1]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Scale.Z")->Value(), &Scale[2]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Offset.X")->Value(), &Offset[0]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Offset.Y")->Value(), &Offset[1]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Offset.Z")->Value(), &Offset[2]);
                        tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Mass")->Value(), &Mass);

                        if (RigidBodyShapeType_Box == (RigidBodyShapeType)shapeType) {
                            tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("BoxHalfExtents.X")->Value(), &BoxHalfExtents[0]);
                            tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("BoxHalfExtents.Y")->Value(), &BoxHalfExtents[1]);
                            tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("BoxHalfExtents.Z")->Value(), &BoxHalfExtents[2]);

                            RigidBody _RigidBody = Physics::CreateShapeBox(BoxHalfExtents[0], BoxHalfExtents[1], BoxHalfExtents[2], Mass, Transform, Rotation, Offset);

                            RigidBodyComponent* rigidBodyComponent = new RigidBodyComponent(_RigidBody);
                            e->AddOrReplaceComponent<RigidBodyComponent>(rigidBodyComponent);
                        }
                        else {
                            AddRigidBodyComponent(e, RigidBodyShapeType_TriangleMesh, Transform, Rotation, Scale, Offset, Mass);
                            //auto& c = *(RigidBodyComponent*)e->GetComponent<RigidBodyComponent>(ComponentType_RigidBody);
                            //c.RigidBodyData.Offset = Offset;
                            //c.RigidBodyData.Mass = Mass;
                            //c.RigidBodyData.Transform = Transform;
                        }
                    }
                    if (strcmp(node_child->Name(), "AnimationComponent") == 0)
                    {
                        bool AnimationLoop;
                        double AnimationMixTime, AnimationSpeed;
                        tinyxml2::XMLUtil::ToBool(node_child->FindAttribute("AnimationLoop")->Value(), &AnimationLoop);

                        tinyxml2::XMLUtil::ToDouble(node_child->FindAttribute("AnimationMixTime")->Value(), &AnimationMixTime);
                        tinyxml2::XMLUtil::ToDouble(node_child->FindAttribute("AnimationSpeed")->Value(), &AnimationSpeed);

                        std::string CurrentAnimatioName = node_child->FindAttribute("CurrentAnimatioName")->Value();

                        AnimationComponent* animationComponent = new AnimationComponent(e->GetAnimationInfo());

                        animationComponent->AnimationLoop = AnimationLoop;
                        animationComponent->AnimationMixTime = AnimationMixTime;
                        animationComponent->AnimationSpeed = AnimationSpeed;

                        std::string AnimList = node_child->FindAttribute("AnimList")->Value();

                        std::stringstream ss(AnimList);
                        std::string item;

                        while (std::getline(ss, item, ',')) {
                            if (!item.empty()) {
                                int index = item.find(":");
                                if (index != -1) {
                                    std::string name = item.substr(0, index);
                                    std::string path = item.substr(index + 1, item.size());
                                    animationComponent->AddAnimation(name, path);
                                    CC_CORE_INFO("load AnimationComponent %s %s\n", name.c_str(), path.c_str());
                                }
                            }
                        }

                        animationComponent->PlayAnimation(CurrentAnimatioName, AnimationLoop);
                        e->AddOrReplaceComponent<AnimationComponent>(animationComponent);
                    }

                    //if (strcmp(node_child->Name(), "MeshComponent") == 0)
                    //{
                    //    Mesh MeshData;                        

                    //    std::string Vertices = node_child->FindAttribute("Vertices")->Value();
                    //    std::string Indices = node_child->FindAttribute("Indices")->Value();
                    //    //std::string Textures = node_child->FindAttribute("Textures")->Value();

                    //    MeshData.ParseVertex(Vertices);
                    //    MeshData.ParseIndices(Indices);
                    //    //c.MeshData.ParseTextures(Textures);

                    //    auto &c = e->AddComponent<MeshComponent>(MeshData);
                    //}

                    //if (strcmp(node_child->Name(), "MeshModelMaterialComponent") == 0)
                    //{
                    //    bool HasColorMaterial;
                    //    float TilingFactor, Shininess;
                    //    float Ambient_R,Ambient_G,Ambient_B,Ambient_A;
                    //    float Diffuse_R,Diffuse_G,Diffuse_B,Diffuse_A;
                    //    float Specular_R,Specular_G,Specular_B,Specular_A;

                    //    tinyxml2::XMLUtil::ToBool(node_child->FindAttribute("HasColorMaterial")->Value(), &HasColorMaterial);
                    //    tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("TilingFactor")->Value(), &TilingFactor);

                    //    tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Ambient.R")->Value(), &Ambient_R);
                    //    tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Ambient.G")->Value(), &Ambient_G);
                    //    tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Ambient.B")->Value(), &Ambient_B);
                    //    tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Ambient.A")->Value(), &Ambient_A);

                    //    tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Diffuse.R")->Value(), &Diffuse_R);
                    //    tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Diffuse.G")->Value(), &Diffuse_G);
                    //    tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Diffuse.B")->Value(), &Diffuse_B);
                    //    tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Diffuse.A")->Value(), &Diffuse_A);

                    //    tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Specular.R")->Value(), &Specular_R);
                    //    tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Specular.G")->Value(), &Specular_G);
                    //    tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Specular.B")->Value(), &Specular_B);
                    //    tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Specular.A")->Value(), &Specular_A);

                    //    tinyxml2::XMLUtil::ToFloat(node_child->FindAttribute("Shininess")->Value(), &Shininess);

                    //    std::string TexturesStr = node_child->FindAttribute("Textures")->Value();

                    //    std::stringstream ss(TexturesStr);
                    //    std::string item;

                    //    std::vector<std::string> array;
                    //    while (std::getline(ss, item, ',')) {
                    //        if (!item.empty()) {
                    //            array.push_back(item);
                    //        }
                    //    }

                    //    std::vector<Texture2D *> Textures;
                    //    for (int i = 0; i < array.size() - 1; i+=1) {
                    //        std::string type = array[i];
                    //        std::string path = array[i+1];
                    //        if (!path.empty())
                    //        {
                    //            Texture2D *t = Texture2D::Create(path);
                    //            t->TypeName = type;
                    //            Textures.push_back(t);
                    //        }
                    //    }

                    //    MaterialMesh MaterialMeshType;
                    //    MaterialMeshType.Ambient = { Ambient_R, Ambient_G, Ambient_B, Ambient_A };
                    //    MaterialMeshType.Diffuse = { Diffuse_R, Diffuse_G, Diffuse_B, Diffuse_A };
                    //    MaterialMeshType.Specular = { Specular_R, Specular_G, Specular_B, Specular_A };
                    //    MaterialMeshType.Shininess = Shininess;
                    //    
                    //    auto &c = e->AddComponent<MeshModelMaterialComponent>(HasColorMaterial, MaterialMeshType, Textures, TilingFactor);
                    //}

                    if (strcmp(node_child->Name(), "Childs") == 0)
                    {
                        AddEntityRecursively(e, *node_child);
                    }
                }
            }
        }
    }


    void Scene::OnWindowResize(WindowResizeEvent &e)
    {
        //OnViewportResize(0, 0, e.GetWidth(), e.GetHeight());
    }

    void Scene::OnWindowFramebufferResize(WindowFramebufferResizeEvent &e)
    {
        OnViewportResize(0, 0, e.GetWidth(), e.GetHeight());
    }

    void Scene::OnMouseButtonMoved(MouseMovedEvent &e)
    {
        m_MouseX = e.GetX();
        m_MouseY = e.GetY();

        if (m_entityHasFocusMouse) {
            auto t = m_entityHasFocusMouse->GetComponent<TransformComponent>(ComponentType_Transform);

            if (m_MouseX < t->Translation[0] || m_MouseX > t->Translation[0] + t->Scale[0]
                || m_MouseY < t->Translation[1] || m_MouseY > t->Translation[1] + t->Scale[1]) {
                //outside
                auto c = m_entityHasFocusMouse->GetComponent<MouseAreaComponent>(ComponentType_MouseArea);
                MouseButtonCancelEvent event(Mouse::Button0);
                c->OnEvent(event, m_entityHasFocusMouse);
                m_entityHasFocusMouse = nullptr;
            }
            else {
                // inside
            }
        }    
    }

    Entity * Scene::CreateArrowAxis(TagType subType, glm::vec4 color, glm::vec3 rotation, glm::vec3 shape, glm::vec3 shapeOffset)
    {
        Entity * e = AddModelNode(m_root, PATHCONFIG("assets/models/arrow.dae"));
   
        CC_ASSERT(e->GetChild(0)->HasComponent(ComponentType_MeshModelMaterial), "CreateArrowAxis error");

        auto mat = e->GetChild(0)->GetComponent<MeshModelMaterialComponent>(ComponentType_MeshModelMaterial);
        mat->HasColorMaterial = true;
        mat->EanbleLight = false;
        mat->MaterialMeshType.Ambient = glm::vec4(1.0);
        mat->MaterialMeshType.Diffuse = color;
        mat->MaterialMeshType.Specular = glm::vec4(1.0);
        mat->MaterialMeshType.Shininess = 0.0;

        auto tag = e->GetComponent<TagComponent>(ComponentType_Tag);
        tag->VisibleEditor = false;
        tag->Type = TagType_Arrow;
        tag->SubType = subType;

        RigidBody _RigidBody = Physics::CreateShapeBox(shape[0], shape[1], shape[2], 0.0, 
            glm::vec3(0.0), glm::vec3(shapeOffset[0], shapeOffset[1], shapeOffset[2]));
        _RigidBody.BtRigidBody->setGravity(btVector3(0.0, 0.0, 0.0));

        RigidBodyComponent* _RigidBodyComponent = new RigidBodyComponent(_RigidBody);
        e->AddComponent(_RigidBodyComponent);

        auto trans = e->GetComponent<TransformComponent>(ComponentType_Transform);
        trans->Rotation = rotation;

        return e;
    }

    void Scene::SetEntityTrans(Entity * e, glm::vec3 trans)
    {
        if (e && e->HasComponent(ComponentType_RigidBody)) {
            SetEntityRigidBodyTransform(e, trans);
        }
        else {
            auto t = e->GetComponent<TransformComponent>(ComponentType_Transform);
            t->Translation = trans;
        }
    }

    void Scene::SetEntityRigidBodyTransform(Entity * e, glm::vec3 trans)
    {
        if (e && e->HasComponent(ComponentType_RigidBody)) {
            auto rigid = e->GetComponent<RigidBodyComponent>(ComponentType_RigidBody);
            btRigidBody *body;

            if (RigidBodyShapeType_Box == rigid->RigidBodyData.RigidBodyShapeTypeValue) {
                body = rigid->RigidBodyData.BtRigidBody;
            }
            else if (RigidBodyShapeType_TriangleMesh == rigid->RigidBodyData.RigidBodyShapeTypeValue) {
                body = rigid->RigidBodyData.BtRigidBodyes[0];
            }
            else {
                body = rigid->RigidBodyData.BtRigidBodyes[0];
            }

            btTransform btrans;
            if (body && body->getMotionState())
            {
                body->getMotionState()->getWorldTransform(btrans);
            }
            else
            {
                btrans = body->getWorldTransform();
            }

            if ((float)btrans.getOrigin().getX() == trans[0] + rigid->RigidBodyData.Offset[0]
                && (float)btrans.getOrigin().getY() == trans[1] + rigid->RigidBodyData.Offset[1]
                && (float)btrans.getOrigin().getZ() == trans[2] + rigid->RigidBodyData.Offset[2]) {
                return;
            }

            //btrans.setIdentity();
            btrans.setOrigin(btVector3((btScalar)(trans[0] + rigid->RigidBodyData.Offset[0]),
                (btScalar)(trans[1] + rigid->RigidBodyData.Offset[1]),
                (btScalar)(trans[2] + rigid->RigidBodyData.Offset[2])));

            body->setCenterOfMassTransform(btrans);
            if (body && body->getMotionState())
            {
                body->getMotionState()->setWorldTransform(btrans);
            }
            else
            {
                body->setWorldTransform(btrans);
            }

            //rigid->RigidBodyData.Transform = trans;
        }
    }

    void Scene::SetEntityRigidBodyRotation(Entity *e, glm::vec3 rotation)
    {
        if (e && e->HasComponent(ComponentType_RigidBody)) {
            auto rigid = e->GetComponent<RigidBodyComponent>(ComponentType_RigidBody);
            btRigidBody *body;

            if (RigidBodyShapeType_Box == rigid->RigidBodyData.RigidBodyShapeTypeValue) {
                body = rigid->RigidBodyData.BtRigidBody;
            }
            else if (RigidBodyShapeType_TriangleMesh == rigid->RigidBodyData.RigidBodyShapeTypeValue) {
                body = rigid->RigidBodyData.BtRigidBodyes[0];
            }
            else {
                body = rigid->RigidBodyData.BtRigidBodyes[0];
            }

            btTransform btrans;
            btQuaternion quaternion;
            if (body && body->getMotionState())
            {
                body->getMotionState()->getWorldTransform(btrans);
                quaternion = btrans.getRotation();
                quaternion.setEulerZYX(rotation[2], rotation[1], rotation[0]);
                btrans.setRotation(quaternion);

                body->setCenterOfMassTransform(btrans);
                body->getMotionState()->setWorldTransform(btrans);
            }
            else
            {
                btrans = body->getWorldTransform();
                quaternion = btrans.getRotation();
                quaternion.setEulerZYX(rotation[2], rotation[1], rotation[0]);
                btrans.setRotation(quaternion);

                body->setCenterOfMassTransform(btrans);
                body->setWorldTransform(btrans);
            }

        }
    }

    glm::vec3 Scene::GetEntityRigidBodyTransform(Entity * e)
    {
        if (e && e->HasComponent(ComponentType_RigidBody)) {
            auto rigid = e->GetComponent<RigidBodyComponent>(ComponentType_RigidBody);
            btRigidBody *body;

            if (RigidBodyShapeType_Box == rigid->RigidBodyData.RigidBodyShapeTypeValue) {
                body = rigid->RigidBodyData.BtRigidBody;
            }
            else if (RigidBodyShapeType_TriangleMesh == rigid->RigidBodyData.RigidBodyShapeTypeValue) {
                body = rigid->RigidBodyData.BtRigidBodyes[0];
            }
            else {
                body = rigid->RigidBodyData.BtRigidBodyes[0];
            }

            btTransform trans;
            if (body && body->getMotionState())
            {
                body->getMotionState()->getWorldTransform(trans);
            }
            else
            {
                trans = body->getWorldTransform();
            }
            return glm::vec3(float(trans.getOrigin().getX() - rigid->RigidBodyData.Offset[0]),
                float(trans.getOrigin().getY() - rigid->RigidBodyData.Offset[1]),
                float(trans.getOrigin().getZ() - rigid->RigidBodyData.Offset[2]));
        }
        return glm::vec3(0.0);
    }

    glm::vec3 Scene::GetEntityRigidBodyTransformNoOffset(Entity * e)
    {
        if (e && e->HasComponent(ComponentType_RigidBody)) {
            auto rigid = e->GetComponent<RigidBodyComponent>(ComponentType_RigidBody);
            btRigidBody *body;

            if (RigidBodyShapeType_Box == rigid->RigidBodyData.RigidBodyShapeTypeValue) {
                body = rigid->RigidBodyData.BtRigidBody;
            }
            else if (RigidBodyShapeType_TriangleMesh == rigid->RigidBodyData.RigidBodyShapeTypeValue) {
                body = rigid->RigidBodyData.BtRigidBodyes[0];
            }
            else {
                body = rigid->RigidBodyData.BtRigidBodyes[0];
            }

            btTransform trans;
            if (body && body->getMotionState())
            {
                body->getMotionState()->getWorldTransform(trans);
            }
            else
            {
                trans = body->getWorldTransform();
            }
            return glm::vec3(float(trans.getOrigin().getX()),
                float(trans.getOrigin().getY()),
                float(trans.getOrigin().getZ()));
        }
        return glm::vec3(0.0);
    }

    glm::vec3 Scene::GetEntityRigidBodyRotation(Entity * e)
    {
        if (e && e->HasComponent(ComponentType_RigidBody)) {
            auto rigid = e->GetComponent<RigidBodyComponent>(ComponentType_RigidBody);
            btRigidBody *body;

            if (RigidBodyShapeType_Box == rigid->RigidBodyData.RigidBodyShapeTypeValue) {
                body = rigid->RigidBodyData.BtRigidBody;
            }
            else if (RigidBodyShapeType_TriangleMesh == rigid->RigidBodyData.RigidBodyShapeTypeValue) {
                body = rigid->RigidBodyData.BtRigidBodyes[0];
            }
            else {
                body = rigid->RigidBodyData.BtRigidBodyes[0];
            }

            btTransform trans;
            if (body && body->getMotionState())
            {
                body->getMotionState()->getWorldTransform(trans);
            }
            else
            {
                trans = body->getWorldTransform();
            }
            btQuaternion orn = trans.getRotation();

            btScalar yawZ;
            btScalar pitchY;
            btScalar rollX;
            orn.getEulerZYX(yawZ, pitchY, rollX);
            return glm::vec3(((float)rollX), ((float)pitchY), ((float)yawZ));
        }
        return glm::vec3(0.0);
    }

    void Scene::AddAnimationProperty(AnimationProperty** anim)
    {
        m_AnimationPropertyes.push_back(anim);
    }

    void Scene::AddAnimationPropertyGroup(AnimationPropertyGroup * animGroup)
    {
        m_AnimationPropertyeGroups.push_back(animGroup);
    }

    void Scene::AddDesktopIcon(DesktopIconInfo & info)
    {
        m_DesktopIconInfos.push_back(info);
    }

    void Scene::AddPhotoIcon(PhotoIconInfo & info)
    {
        m_PhotoIconInfos.push_back(info);
    }

    void Scene::AddVideoInfo(VideoInfo & info)
    {
        m_VideoInfos.push_back(info);
    }

    void Scene::RemoveAnimationProperty(AnimationProperty * anim)
    {
    }

    Entity *Scene::GetEntityByUUID(UUID uuid)
    {
        // TODO(Yan): Maybe should be assert
        /*if (m_EntityMap.find(uuid) != m_EntityMap.end())
            return m_EntityMap[uuid];
*/
        return nullptr;
    }

    void Scene::RenderScene2D(Camera *camera, glm::mat4 cameraTransform, Timestep ts)
    {
        CC_ASSERT(m_root != nullptr, "ASSERT: Scene::RenderScene2D m_root=null\n");

        Renderer2D::BeginScene(camera, cameraTransform, m_FramebufferData2D);

        RenderEnityty2D(m_root, glm::mat4(1.0), ts);
        Renderer2D::EndScene();
    }

    void Scene::RenderScene3D(Camera *camera, glm::mat4 cameraTransform, Timestep ts)
    {
        CC_ASSERT(m_root != nullptr, "ASSERT: Scene::RenderScene3D m_root=null\n");
        Renderer3D::BeginScene(camera, cameraTransform, m_FramebufferData);

        RenderEnityty3D(m_root, glm::mat4(1.0), glm::vec3(1.0, 1.0, 1.0), ts, "opaque");
        RenderEnityty3D(m_root, glm::mat4(1.0), glm::vec3(1.0, 1.0, 1.0), ts, "transparent");
        Renderer3D::EndScene();
    }

    void Scene::RenderScene3DDebugPhysics(Camera * camera, glm::mat4 cameraTransform, Timestep ts)
    {
        CC_ASSERT(m_root != nullptr, "ASSERT: Scene::RenderScene3D m_root=null\n");
        Renderer3D::BeginScene(camera, cameraTransform, m_FramebufferData, m_DebugPhysics);

        RenderEnityty3DDebugPhysics(m_root, glm::mat4(1.0), glm::vec3(1.0, 1.0, 1.0), ts);
        Renderer3D::EndScene();

        //m_dynamicsWorld->debugDrawWorld();
    }

    void Scene::RenderEnityty2D(Entity *e, glm::mat4 parentTransform, Timestep ts)
    {
        if (!e)
            return;

        glm::mat4 globalTransformation = glm::mat4(1.0);
        bool canDraw = true;// renderPass == e->GetComponent<TagComponent>(ComponentType_Tag)->RenderPassTag;

        if (m_FramebufferData2D && "" != m_FramebufferData2D->GetSpecification().RenderPass) {
            canDraw = m_FramebufferData2D->GetSpecification().RenderPass == e->GetComponent<TagComponent>(ComponentType_Tag)->RenderPassTag;
        }

        if (!e->GetComponent<TagComponent>(ComponentType_Tag)->Visible) {
            return;
        }

        if (e->GetComponent<TagComponent>(ComponentType_Tag)->Type == TagType_FPS) {
            //
            auto fc = e->GetComponent<FontComponent>(ComponentType_Font);
            fc->wtext = string_to_wstring(Tool::Int2Str(Application::Get().GetFpsValueInt()));
        }

        if (e->HasComponent(ComponentType_Material2D) && e->HasComponent(ComponentType_Font) && e->HasComponent(ComponentType_Transform))
        {
            auto fc = e->GetComponent<FontComponent>(ComponentType_Font);
            auto transform = e->GetComponent<TransformComponent>(ComponentType_Transform);
            auto sprite = e->GetComponent<Material2DComponent>(ComponentType_Material2D);

            globalTransformation = parentTransform * transform->GetTransformNoScale();
            if (canDraw) {
                Renderer2D::DrawFont(parentTransform, *fc, *transform, *sprite, (int)e);
            }            
        }
        else if (e->HasComponent(ComponentType_Transform) && e->HasComponent(ComponentType_Material2D) 
        && e->HasComponent(ComponentType_Particle2D))
        {
            auto sprite = e->GetComponent<Material2DComponent>(ComponentType_Material2D);
            auto transform = e->GetComponent<TransformComponent>(ComponentType_Transform);
            auto particle2D = e->GetComponent<Particle2DComponent>(ComponentType_Particle2D);
            auto emitter = particle2D->GetEmitter();

            particle2D->Update(ts.GetSeconds());

            globalTransformation = parentTransform * transform->GetTransformNoScale();
            glm::mat4 currentMat = parentTransform * transform->GetTransform();

            auto shaderc = e->GetComponent<ShaderComponent>(ComponentType_Shader);
            auto custom2DMaterial = e->GetComponent<Custom2DMaterialComponent>(ComponentType_Custom2DMaterial);
            if (shaderc) {
                if (canDraw) {
                    Renderer2D::DrawPriticle(currentMat, *sprite, *emitter, *particle2D, *shaderc, custom2DMaterial, (int)e);
                }
            }
            else {
                if (canDraw) {
                    Renderer2D::DrawPriticle(currentMat, *sprite, *emitter, *particle2D, (int)e);
                }
            }
        }
        else if (e->HasComponent(ComponentType_Transform) && e->HasComponent(ComponentType_Material2D))
        {
            auto sprite = e->GetComponent<Material2DComponent>(ComponentType_Material2D);
            auto transform = e->GetComponent<TransformComponent>(ComponentType_Transform);

            globalTransformation = parentTransform * transform->GetTransformNoScale();
            glm::mat4 currentMat = parentTransform * transform->GetTransform();

            auto shaderc = e->GetComponent<ShaderComponent>(ComponentType_Shader);
            auto custom2DMaterial = e->GetComponent<Custom2DMaterialComponent>(ComponentType_Custom2DMaterial);
            if (shaderc) {
                if (canDraw) {
                    Renderer2D::DrawSprite(currentMat, *sprite, *shaderc, custom2DMaterial, (int)e);
                }
            }
            else {
                if (canDraw) {
                    Renderer2D::DrawSprite(currentMat, *sprite, (int)e);
                }
            }
        }
        else if (e->HasComponent(ComponentType_Transform))
        {
            auto transform = e->GetComponent<TransformComponent>(ComponentType_Transform);
            globalTransformation = parentTransform * transform->GetTransformNoScale();
        }

        int len = e->GetChildCount();
        for (int i = 0; i < len; i++)
        {
            RenderEnityty2D(e->GetChild(i), globalTransformation, ts);
        }
    }

    void Scene::RenderEnityty3D(Entity *e, glm::mat4 parentTransform, glm::vec3 parentScale, Timestep ts, std::string renderPass)
    {
        if (!e)
            return;

        glm::mat4 globalTransformation = glm::mat4(1.0);
        glm::vec3 globalScale = glm::vec3(1.0, 1.0, 1.0);

        if (!e->GetComponent<TagComponent>(ComponentType_Tag)->Visible) {
            return;
        }

        if (TagType_Arrow == e->GetComponent<TagComponent>(ComponentType_Tag)->Type) {
            return;
        }

        bool canDraw = renderPass == e->GetComponent<TagComponent>(ComponentType_Tag)->RenderPassTag;

        if (m_FramebufferData && "" != m_FramebufferData->GetSpecification().RenderPass) {
            canDraw = m_FramebufferData->GetSpecification().RenderPass == e->GetComponent<TagComponent>(ComponentType_Tag)->RenderPassTag;
        }

        if (e->HasComponent(ComponentType_RigidBody) && e->HasComponent(ComponentType_Transform))
        {
            // update physics->trans
            //parentTransform = glm::mat4(1.0);
            
            auto transform = e->GetComponent<TransformComponent>(ComponentType_Transform);
            transform->Translation = GetEntityRigidBodyTransform(e);
            transform->Rotation = GetEntityRigidBodyRotation(e);

            auto c = e->GetComponent<RigidBodyComponent>(ComponentType_RigidBody);
            c->RigidBodyData.Transform = transform->Translation;
            c->RigidBodyData.Rotation = transform->Rotation;
        }

        if (e->HasComponent(ComponentType_Animation))
        {
            auto anim = e->GetComponent<AnimationComponent>(ComponentType_Animation);
            if (anim->CurrentAnimatioName != "")
            {
                anim->AnimatorObject->UpdateAnimation(ts.GetSeconds() * anim->AnimationSpeed, anim->AnimationLoop, anim->AnimationFinish, anim->AnimationCurrentFrame);

                // if (anim.AnimationFinish)
                // {
                //     anim.AnimationFinish = true;
                //     anim.PlayAnimation(anim.LastAnimatioName); // back to last animation
                // }
            }
        }

        if (e->HasComponent(ComponentType_Font))
        {
        }
        else if (e->HasComponent(ComponentType_MeshBasicMaterial) && e->HasComponent(ComponentType_Transform))
        {
            auto sprite = e->GetComponent<MeshBasicMaterialComponent>(ComponentType_MeshBasicMaterial);
            auto transform = e->GetComponent<TransformComponent>(ComponentType_Transform);

            globalTransformation = parentTransform * transform->GetTransform();
            //globalScale = parentScale * transform->Scale;

            glm::vec3 pScale = e->GetParent()->GetComponent<TransformComponent>(ComponentType_Transform)->Scale;

            if (canDraw) {
                Renderer3D::DrawSprite(globalTransformation, *sprite, (int)e);
            }     
        }
        else if (e->HasComponent(ComponentType_MeshCubeMaterial) && e->HasComponent(ComponentType_Transform))
        {
            auto sprite = e->GetComponent<MeshCubeMaterialComponent>(ComponentType_MeshCubeMaterial);
            auto transform = e->GetComponent<TransformComponent>(ComponentType_Transform);

            globalTransformation = parentTransform * transform->GetTransform();
            //globalScale = parentScale * transform->Scale;

            glm::vec3 pScale = e->GetParent()->GetComponent<TransformComponent>(ComponentType_Transform)->Scale;

            if (canDraw) {
                Renderer3D::DrawSkybox(globalTransformation, *sprite, (int)e);
            }
        }
        else if (e->HasComponent(ComponentType_MeshModelMaterial) && e->HasComponent(ComponentType_Mesh) && e->HasComponent(ComponentType_Transform))
        {
            auto material = e->GetComponent<MeshModelMaterialComponent>(ComponentType_MeshModelMaterial);
            auto mesh = e->GetComponent<MeshComponent>(ComponentType_Mesh);
            auto transform = e->GetComponent<TransformComponent>(ComponentType_Transform);

            globalTransformation = parentTransform * transform->GetTransform();
            //globalScale = parentScale * transform->Scale;

            //glm::vec3 pScale = e->GetParent()->GetComponent<TransformComponent>(ComponentType_Transform)->Scale;

            Entity *parent = e->GetParent();
            if (parent && parent->HasComponent(ComponentType_Animation))
            {
                auto animation = parent->GetComponent<AnimationComponent>(ComponentType_Animation);
                if (animation->CurrentAnimatioName != "") {
                    auto shaderc = e->GetComponent<ShaderComponent>(ComponentType_Shader);
                    if (shaderc) {
                        if (canDraw) {
                            Renderer3D::DrawModelAnimCustomShader(globalTransformation, *material, *mesh, *animation, *shaderc, e);
                        }                        
                    }
                    else {
                        if (canDraw) {
                            Renderer3D::DrawModelAnim(globalTransformation, *material, *mesh, *animation, (int)e);
                        }                        
                    }                    
                }
            }
            else
            {
                auto shaderc = e->GetComponent<ShaderComponent>(ComponentType_Shader);
                if (shaderc) {
                    if (canDraw) {
                        Renderer3D::DrawModelNoAnimCustomShader(globalTransformation, *material, *mesh, *shaderc, e);
                    }                    
                }
                else {
                    if (canDraw) {
                        Renderer3D::DrawModelNoAnim(globalTransformation, *material, *mesh, (int)e);
                    }                    
                }
            }
        }
        else if (e->HasComponent(ComponentType_Transform))
        {
            auto transform = e->GetComponent<TransformComponent>(ComponentType_Transform);
            globalTransformation = parentTransform * transform->GetTransform();
            //globalScale = parentScale * transform->Scale;
        }

        int len = e->GetChildCount();
        for (int i = 0; i < len; i++)
        {
            RenderEnityty3D(e->GetChild(i), globalTransformation, globalScale, ts, renderPass);
        }
    }

    void Scene::RenderEnityty3DDebugPhysics(Entity * e, glm::mat4 parentTransform, glm::vec3 parentScale, Timestep ts)
    {
        if (!e)
            return;

        glm::mat4 globalTransformation = glm::mat4(1.0);
        glm::vec3 globalScale = glm::vec3(1.0, 1.0, 1.0);

        if (!e->GetComponent<TagComponent>(ComponentType_Tag)->Visible) {
            return;
        }

        if (!m_MoveAxisDisplay && TagType_Arrow == e->GetComponent<TagComponent>(ComponentType_Tag)->Type) {
            return;
        }

        if (e->HasComponent(ComponentType_RigidBody) && e->HasComponent(ComponentType_Transform))
        {
            // update physics->trans
            //parentTransform = glm::mat4(1.0);

            auto transform = e->GetComponent<TransformComponent>(ComponentType_Transform);
            auto c = e->GetComponent<RigidBodyComponent>(ComponentType_RigidBody);

            if (RigidBodyShapeType_Box == c->RigidBodyData.RigidBodyShapeTypeValue) {
                int colorIndex = c->RigidBodyData.BtRigidBody->getBroadphaseHandle()->getUid() & 3;
                btVector4 color;
                color = sColors[colorIndex];

                TransformComponent _tran = *transform;

                glm::vec3 t = GetEntityRigidBodyTransformNoOffset(e);
                glm::vec3 halfExtents = c->RigidBodyData.BoxHalfExtents;

                _tran.Translation = t;
                _tran.Scale = halfExtents;

                globalTransformation = parentTransform * _tran.GetTransform();
                //globalScale = parentScale * _tran.Scale;
                
                //Renderer3D::DrawBoxBorder(t, 
                //    glm::vec3(transform->Rotation[2], transform->Rotation[1], transform->Rotation[0]),
                //    halfExtents, Tool::GetGLMVec4(color));

                Renderer3D::DrawBoxBorder(globalTransformation, Tool::GetGLMVec4(color));
            }
            else if (RigidBodyShapeType_TriangleMesh == c->RigidBodyData.RigidBodyShapeTypeValue) {
                if (c->RigidBodyData.MeshModelMaterialComponentDebug && c->RigidBodyData.MeshComponentDebug) {
                    TransformComponent _tran = *transform;
                    //_tran.Scale = c->RigidBodyData.Scale;
                    _tran.Scale = glm::vec3(1.0) / parentScale;

                    globalTransformation = parentTransform * _tran.GetTransform();
                    //globalScale = parentScale * _tran.Scale;

                    int colorIndex = c->RigidBodyData.BtRigidBodyes[0]->getBroadphaseHandle()->getUid() & 3;
                    btVector4 color;
                    color = sColors[colorIndex];
                    ((MeshModelMaterialComponent*)c->RigidBodyData.MeshModelMaterialComponentDebug)->MaterialMeshType.Diffuse = Tool::GetGLMVec4(color);

                    Renderer3D::DrawTriangleBorder(globalTransformation, *(MeshModelMaterialComponent*)c->RigidBodyData.MeshModelMaterialComponentDebug, *(MeshComponent*)c->RigidBodyData.MeshComponentDebug);
                }                
            }
        }
        else if (e->HasComponent(ComponentType_LineBasicMaterial) && e->HasComponent(ComponentType_Transform))
        {
            parentTransform = glm::mat4(1.0);

            auto c = e->GetComponent<LineBasicMaterialComponent>(ComponentType_LineBasicMaterial);
            Renderer3D::DrawLine(c->StartPoint, c->EndPoint, c->Color);
        }
        else if (e->HasComponent(ComponentType_Transform))
        {
            auto transform = e->GetComponent<TransformComponent>(ComponentType_Transform);
            globalTransformation = parentTransform * transform->GetTransform();
            //globalScale = parentScale * transform->Scale;
        }

        int len = e->GetChildCount();
        for (int i = 0; i < len; i++)
        {
            RenderEnityty3DDebugPhysics(e->GetChild(i), globalTransformation, parentScale, ts);
        }
    }

    void Scene::SetDisplayMode(DisplayModesEnum mode)
    {
        m_DisplayMode = mode;
        Renderer2D::SetDisplayMode(mode);
    }

    void Scene::SetLightPos(const glm::vec4 &pos)
    {
        /*Entity *e = FindEntityByName("Light");
        if (!e)
            return;

        auto &t = e->GetComponent<TransformComponent>();
        t.Translation = pos;*/
        Renderer3D::SetLightPos(pos);
    }

    glm::vec3 Scene::GetLightPos()
    {
        return Renderer3D::GetLightPos();
    }

    void Scene::SetLightColor(const glm::vec4 & c)
    {
        Renderer3D::SetLightColor(c);
    }

    glm::vec4 Scene::GetLightColor()
    {
        return Renderer3D::GetLightColor();
    }

    void Scene::SetLightIntensity(const float& value)
    {
        Renderer3D::SetLightIntensity(value);
    }

    float Scene::GetLightIntensity()
    {
        return Renderer3D::GetLightIntensity();
    }

    void Scene::OnEvent(Event &e)
    {
        EventDispatcher dispatcher(e);
        dispatcher.Dispatch<WindowResizeEvent>(std::bind(&Scene::OnWindowResize, this, std::placeholders::_1));
        dispatcher.Dispatch<WindowFramebufferResizeEvent>(std::bind(&Scene::OnWindowFramebufferResize, this, std::placeholders::_1));
        dispatcher.Dispatch<MouseMovedEvent>(std::bind(&Scene::OnMouseButtonMoved, this, std::placeholders::_1));

        if (m_OrthographicCamera)
        {
            m_OrthographicCamera->OnEvent(e);
        }
        if (m_PerspectiveCamera)
        {
            m_PerspectiveCamera->OnEvent(e);
        }
        if (m_EditPerspectiveCamera)
        {
            m_EditPerspectiveCamera->OnEvent(e);
        }

        OnEventMouseAreaRecursion(m_root, e);
        OnEventScriptRecursion(m_root, e);
    }

    void Scene::SaveToXmlEngine(std::string filepath)
    {
        if (!filepath.empty())
        {

            //clear ScriptData.h
            m_scriptData = "#pragma once\n";  
            m_scriptDataFunction = "#define HANDLEFUNCTION(c) {\\\n";

            tinyxml2::XMLDocument doc;
            const char *declaration = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>";
            doc.Parse(declaration);

            tinyxml2::XMLElement *element = doc.NewElement("Root");
            doc.InsertEndChild(element);
            SaveEntityRecursivelyEngine(m_root, doc, *element);

            doc.SaveFile(filepath.c_str(), false);

            m_scriptDataFunction += "}";

            std::string sd = PATHCONFIG("assets/ScriptData.h");
#define DEV (0)
            if (DEV) {
                sd = PATHCONFIG("../Sandbox/assets/ScriptData.h");
            }
            FileLog::WriteFile(sd, m_scriptData+ m_scriptDataFunction);
        }
    }

    void Scene::ReadFromXmlEngine(std::string filepath)
    {
        if(filepath.empty()) return;

        // clear
        DestroyEntity(m_root);

        m_root = nullptr;
        m_ArrowGlobalAxisX = nullptr;
        m_ArrowGlobalAxisY = nullptr;
        m_ArrowGlobalAxisZ = nullptr;
        m_root = CreateRoot("root");

        // Parse the XML document from the memory and release the open file.
        tinyxml2::XMLDocument doc;
        tinyxml2::XMLError error = doc.LoadFile(filepath.c_str());

        // If the plugin successfully loads the file set in the XML Data Source File property, create data objects.
        if (error == tinyxml2::XML_SUCCESS)
        {
            // Get the root XML element.
            tinyxml2::XMLElement *element = doc.RootElement();
            AddEntityRecursivelyEngine(m_root, *element);
        }
        else
        {
            CC_CORE_INFO("tinyxml2::XMLError\n");
        }
      
    }

    void Scene::SaveToXml(std::string filepath)
    {
        if (!filepath.empty())
        {

            tinyxml2::XMLDocument doc;
            const char *declaration = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>";
            doc.Parse(declaration);

            tinyxml2::XMLElement *element = doc.NewElement("Root");
            doc.InsertEndChild(element);
            SaveEntityRecursively(m_root, doc, *element);

            doc.SaveFile(filepath.c_str(), false);

        }
    }

    void Scene::ReadFromXml(std::string filepath)
    {
        if (filepath.empty()) return;

        // clear

        // Parse the XML document from the memory and release the open file.
        tinyxml2::XMLDocument doc;
        tinyxml2::XMLError error = doc.LoadFile(filepath.c_str());

        // If the plugin successfully loads the file set in the XML Data Source File property, create data objects.
        if (error == tinyxml2::XML_SUCCESS)
        {
            // Get the root XML element.
            tinyxml2::XMLElement *element = doc.RootElement();
            AddEntityRecursively(m_root, *element);
        }
        else
        {
            CC_CORE_INFO("tinyxml2::XMLError\n");
        }

    }


    void Scene::SetUseEditCamera(bool r)
    {
        CC_ASSERT(m_EditPerspectiveCamera != nullptr && m_PerspectiveCamera != nullptr, "ASSERT: SetUseEditCamera\n");
         m_EditPerspectiveCamera->SetPosition(m_PerspectiveCamera->GetPosition());
         m_EditPerspectiveCamera->SetProjection(m_PerspectiveCamera->GetFovy(), m_PerspectiveCamera->GetAspect(), 0.01, 1000.0);
         
         /*
        if (m_PerspectiveCamera->GetHasLookAt()) {
            m_EditPerspectiveCamera->SetTargetPosition(m_PerspectiveCamera->GetTargetPosition());
        }
        else {
            m_EditPerspectiveCamera->SetRotationPitch(m_PerspectiveCamera->GetRotationPitch());
            m_EditPerspectiveCamera->SetRotationYaw(m_PerspectiveCamera->GetRotationYaw());
        }
        m_EditPerspectiveCamera->SetHasLookAt(m_PerspectiveCamera->GetHasLookAt());*/

        m_EditPerspectiveCamera->SetTargetPosition(m_PerspectiveCamera->GetTargetPosition());
        m_EditPerspectiveCamera->SetHasLookAt(true);
        m_UseEditCamera = r;
    }

    void Scene::SaveEditCamera()
    {
        CC_ASSERT(m_EditPerspectiveCamera != nullptr && m_PerspectiveCamera != nullptr, "ASSERT: SaveEditCamera\n");
        m_PerspectiveCamera->SetPosition(m_EditPerspectiveCamera->GetPosition());        
        m_PerspectiveCamera->SetProjection(m_EditPerspectiveCamera->GetFovy(), m_EditPerspectiveCamera->GetAspect(), 0.01, 1000.0);
        m_PerspectiveCamera->SetRotationPitch(m_EditPerspectiveCamera->GetRotationPitch());
        m_PerspectiveCamera->SetRotationYaw(m_EditPerspectiveCamera->GetRotationYaw());
        m_PerspectiveCamera->SetTargetPosition(m_EditPerspectiveCamera->GetTargetPosition());

        if (m_EditPerspectiveCamera->GetHasLookAt()) {
            m_PerspectiveCamera->SetTargetPosition(m_EditPerspectiveCamera->GetTargetPosition());
        }
        else {
            m_PerspectiveCamera->SetRotationPitch(m_EditPerspectiveCamera->GetRotationPitch());
            m_PerspectiveCamera->SetRotationYaw(m_EditPerspectiveCamera->GetRotationYaw());
        }
        m_PerspectiveCamera->SetHasLookAt(m_EditPerspectiveCamera->GetHasLookAt());
    }

    btVector3 Scene::GetRayTo(int x, int y)
    {
        if (!m_mainCamera3d)
            return btVector3(0, 0, 0);

        float top = 1.f;
        float bottom = -1.f;
        float nearPlane = 1.f;
        // float tanFov = (top - bottom) * 0.5f / nearPlane;
        // float fov = btScalar(2.0) * btAtan(tanFov);
        float fov = m_mainCamera3d->GetFovyRadian();
        float tanFov = btTan(fov);

        btVector3 camPos, camTarget;

        camPos = Tool::GetVec3GLM(m_mainCamera3d->GetPosition());
        camTarget = Tool::GetVec3GLM(m_mainCamera3d->GetTargetPosition());

        btVector3 rayFrom = camPos;
        btVector3 rayForward = (camTarget - camPos);
        rayForward.normalize();
        float farPlane = 1000.f;
        rayForward *= farPlane;

        btVector3 rightOffset;
        btVector3 cameraUp = btVector3(0, 0, 0);

        cameraUp = Tool::GetVec3GLM(m_mainCamera3d->GetUpAxis());

        btVector3 vertical = cameraUp;

        btVector3 hor;
        hor = rayForward.cross(vertical);
        hor.safeNormalize();
        vertical = hor.cross(rayForward);
        vertical.safeNormalize();

        float tanfov = tanf(0.5f * fov);

        hor *= 2.f * farPlane * tanfov;
        vertical *= 2.f * farPlane * tanfov;

        btScalar aspect;
        float width = float(m_ViewportWidth);
        float height = float(m_ViewportHeight);

        CC_ASSERT(width != 0.0 && height != 0.0, "ASSERT: width=%f || height=%f\n", width, height);

        aspect = width / height;

        hor *= aspect;

        btVector3 rayToCenter = rayFrom + rayForward;
        btVector3 dHor = hor * 1.f / width;
        btVector3 dVert = vertical * 1.f / height;

        btVector3 rayTo = rayToCenter - 0.5f * hor + 0.5f * vertical;
        rayTo += btScalar(x) * dHor;
        rayTo -= btScalar(y) * dVert;
        return rayTo;
    }

    bool Scene::PickBody(const btVector3 &rayFromWorld, const btVector3 &rayToWorld, Entity** entity)
    {
        if (m_dynamicsWorld == 0)
            return false;

        btCollisionWorld::ClosestRayResultCallback rayCallback(rayFromWorld, rayToWorld);

        m_dynamicsWorld->rayTest(rayFromWorld, rayToWorld, rayCallback);
        if (rayCallback.hasHit())
        {
            btVector3 pickPos = rayCallback.m_hitPointWorld;
            btRigidBody *body = (btRigidBody *)btRigidBody::upcast(rayCallback.m_collisionObject);
            if (body)
            {
                // other exclusions?
                if (!(body->isStaticObject() || body->isKinematicObject()))
                {
                    m_pickedBody = body;
                    m_savedState = m_pickedBody->getActivationState();
                    m_pickedBody->setActivationState(DISABLE_DEACTIVATION);
                    //CC_CORE_INFO("pickPos=%f,%f,%f\n", pickPos.getX(), pickPos.getY(), pickPos.getZ());
                    btVector3 localPivot = body->getCenterOfMassTransform().inverse() * pickPos;
                    btPoint2PointConstraint *p2p = new btPoint2PointConstraint(*body, localPivot);
                    m_dynamicsWorld->addConstraint(p2p, true);
                    m_pickedConstraint = p2p;
                    btScalar mousePickClamping = 3.f;
                    p2p->m_setting.m_impulseClamp = mousePickClamping;
                    // very weak constraint for picking
                    p2p->m_setting.m_tau = 0.001f;

                    *entity = FindEntityByRigidBoy(body);
                }
            }

            //					pickObject(pickPos, rayCallback.m_collisionObject);
            m_oldPickingPos = rayToWorld;
            m_hitPos = pickPos;
            m_oldPickingDist = (pickPos - rayFromWorld).length();
            //					printf("hit !\n");

            // add p2p
            if(*entity) return true;
        }
        return false;
    }

    bool Scene::PickDynamicCloseBody(const btVector3 &rayFromWorld, const btVector3 &rayToWorld, Entity** entity)
    {
        if (m_dynamicsWorld == 0)
            return false;

        btCollisionWorld::ClosestRayResultCallback rayCallback(rayFromWorld, rayToWorld);

        m_dynamicsWorld->rayTest(rayFromWorld, rayToWorld, rayCallback);
        if (rayCallback.hasHit())
        {
            btVector3 pickPos = rayCallback.m_hitPointWorld;
            btRigidBody *body = (btRigidBody *)btRigidBody::upcast(rayCallback.m_collisionObject);
            if (body)
            {
                // other exclusions?
                if (!(body->isStaticObject() || body->isKinematicObject()))
                {
                    *entity = FindEntityByRigidBoy(body);
                    return true;
                }
            }
        }
        return false;
    }

    bool Scene::PickStaticBody(const btVector3 &rayFromWorld, const btVector3 &rayToWorld, Entity** entity, float* pickpos)    
    {
        if (m_dynamicsWorld == 0)
            return false;

        m_pickedStaticBody = NULL;

        btCollisionWorld::ClosestRayResultCallback rayCallback(rayFromWorld, rayToWorld);

        m_dynamicsWorld->rayTest(rayFromWorld, rayToWorld, rayCallback);
        if (rayCallback.hasHit())
        {
            btVector3 pickPos = rayCallback.m_hitPointWorld;
            pickpos[0] = pickPos[0];
            pickpos[1] = pickPos[1];
            pickpos[2] = pickPos[2];
            btRigidBody *body = (btRigidBody *)btRigidBody::upcast(rayCallback.m_collisionObject);
            if (body)
            {
                // other exclusions?
                if ((body->isStaticObject() || body->isKinematicObject()))
                {
                    m_pickedStaticBody = body;
                }
            }

            if (m_pickedStaticBody) {
                *entity = FindEntityByRigidBoy(m_pickedStaticBody);
            }
            if (body) return true;
        }
        return false;
    }

    std::vector<btRigidBody*> Scene::PickAllStaticBody(const btVector3 &rayFromWorld, const btVector3 &rayToWorld)
    {
        std::vector<btRigidBody*> v;
        if (m_dynamicsWorld == 0)
            return v;

        btCollisionWorld::AllHitsRayResultCallback rayCallback(rayFromWorld, rayToWorld);

        m_dynamicsWorld->rayTest(rayFromWorld, rayToWorld, rayCallback);
        for (int i = 0; i < rayCallback.m_collisionObjects.size(); i++) {
            if (rayCallback.m_collisionObjects[i]) {
                btRigidBody *body = (btRigidBody *)btRigidBody::upcast(rayCallback.m_collisionObjects[i]);
                if (body) {
                    v.push_back(body);
                }
            }
        }
        return v;
    }

    bool Scene::PickAllStaticBodyFilter(const btVector3 &rayFromWorld, const btVector3 &rayToWorld, Entity** entity, float* pickpos, std::vector<Entity*> filterObjectes)
    {
        if (m_dynamicsWorld == 0)
            return false;

        btCollisionWorld::AllHitsRayResultCallback rayCallback(rayFromWorld, rayToWorld);

        m_dynamicsWorld->rayTest(rayFromWorld, rayToWorld, rayCallback);
       // if (rayCallback.hasHit())
        //{
            for (int i = 0; i < rayCallback.m_collisionObjects.size(); i++) {
                if (rayCallback.m_collisionObjects[i]) {
                    btVector3 pickPos = rayCallback.m_hitPointWorld[i];
                    pickpos[0] = pickPos[0];
                    pickpos[1] = pickPos[1];
                    pickpos[2] = pickPos[2];
                    btRigidBody *body = (btRigidBody *)btRigidBody::upcast(rayCallback.m_collisionObjects[i]);
                    if (body)
                    {
                        // other exclusions?
                        if ((body->isStaticObject() || body->isKinematicObject()))
                        {
                            for (int x = 0; x < filterObjectes.size(); x++) {
                                if (filterObjectes[x]->HasComponent(ComponentType_RigidBody) && body == filterObjectes[x]->GetComponent<RigidBodyComponent>(ComponentType_RigidBody)->RigidBodyData.BtRigidBody) {

                                    *entity = filterObjectes[x];
                                    return true;
                                }
                            }
                        }
                                                
                    }
                    
                }
            }
            
        //}
        return false;
    }

    bool Scene::PickAllBodyFilter(const btVector3 &rayFromWorld, const btVector3 &rayToWorld, Entity** entity, float* pickpos, std::vector<Entity*> filterObjectes)
    {
        if (m_dynamicsWorld == 0)
            return false;

        btCollisionWorld::AllHitsRayResultCallback rayCallback(rayFromWorld, rayToWorld);

        m_dynamicsWorld->rayTest(rayFromWorld, rayToWorld, rayCallback);
        // if (rayCallback.hasHit())
         //{
        for (int i = 0; i < rayCallback.m_collisionObjects.size(); i++) {
            if (rayCallback.m_collisionObjects[i]) {
                btVector3 pickPos = rayCallback.m_hitPointWorld[i];
                pickpos[0] = pickPos[0];
                pickpos[1] = pickPos[1];
                pickpos[2] = pickPos[2];
                btRigidBody *body = (btRigidBody *)btRigidBody::upcast(rayCallback.m_collisionObjects[i]);
                if (body)
                {
                    // other exclusions?
                    //if ((body->isStaticObject() || body->isKinematicObject()))
                    {
                        for (int x = 0; x < filterObjectes.size(); x++) {
                            if (filterObjectes[x]->HasComponent(ComponentType_RigidBody) && body == filterObjectes[x]->GetComponent<RigidBodyComponent>(ComponentType_RigidBody)->RigidBodyData.BtRigidBody) {

                                *entity = filterObjectes[x];
                                return true;
                            }
                        }
                    }

                }

            }
        }

        //}
        return false;
    }

    bool Scene::PickAllBodyFilterExclude(const btVector3 & rayFromWorld, const btVector3 & rayToWorld, Entity ** entity, float * pickpos, std::vector<Entity*> filterObjectes)
    {
        if (m_dynamicsWorld == 0)
            return false;

        btCollisionWorld::AllHitsRayResultCallback rayCallback(rayFromWorld, rayToWorld);

        m_dynamicsWorld->rayTest(rayFromWorld, rayToWorld, rayCallback);
        // if (rayCallback.hasHit())
         //{
        for (int i = 0; i < rayCallback.m_collisionObjects.size(); i++) {
            if (rayCallback.m_collisionObjects[i]) {
                btVector3 pickPos = rayCallback.m_hitPointWorld[i];
                pickpos[0] = pickPos[0];
                pickpos[1] = pickPos[1];
                pickpos[2] = pickPos[2];
                btRigidBody *body = (btRigidBody *)btRigidBody::upcast(rayCallback.m_collisionObjects[i]);
                if (body)
                {
                    // other exclusions?
                    //if ((body->isStaticObject() || body->isKinematicObject()))
                    {
                        bool find = false;
                        for (int x = 0; x < filterObjectes.size(); x++) {
                            if (filterObjectes[x]->HasComponent(ComponentType_RigidBody) && body == filterObjectes[x]->GetComponent<RigidBodyComponent>(ComponentType_RigidBody)->RigidBodyData.BtRigidBody) {

                                find = true;
                                break;
                            }
                        }
                        if (find) {
                            continue;
                        }
                        else {   
                            *entity = FindEntityByRigidBoy(body);
                            return true;
                        }
                    }

                }

            }
        }
        return false;
    }

    bool Scene::MovePickedBody(const btVector3 &rayFromWorld, const btVector3 &rayToWorld)
    {
        if (m_pickedBody && m_pickedConstraint)
        {
            btPoint2PointConstraint *pickCon = static_cast<btPoint2PointConstraint *>(m_pickedConstraint);
            if (pickCon)
            {
                // keep it at the same picking distance

                btVector3 newPivotB;

                btVector3 dir = rayToWorld - rayFromWorld;
                dir.normalize();
                dir *= m_oldPickingDist;

                newPivotB = rayFromWorld + dir;
                pickCon->setPivotB(newPivotB);
                return true;
            }
        }
        return false;
    }

    void Scene::RemovePickingConstraint()
    {
        if (m_pickedConstraint)
        {
            m_pickedBody->forceActivationState(m_savedState);
            m_pickedBody->activate();
            m_dynamicsWorld->removeConstraint(m_pickedConstraint);
            delete m_pickedConstraint;
            m_pickedConstraint = 0;
            m_pickedBody = 0;
        }
    }

    Entity * Scene::PickEntity(const btVector3 & rayFromWorld, const btVector3 & rayToWorld, float * pickpos)
    {
        if (m_dynamicsWorld == 0)
            return nullptr;

        btCollisionWorld::ClosestRayResultCallback rayCallback(rayFromWorld, rayToWorld);

        m_dynamicsWorld->rayTest(rayFromWorld, rayToWorld, rayCallback);
        if (rayCallback.hasHit())
        {
            btVector3 pickPos = rayCallback.m_hitPointWorld;
            pickpos[0] = pickPos[0];
            pickpos[1] = pickPos[1];
            pickpos[2] = pickPos[2];
            btRigidBody *body = (btRigidBody *)btRigidBody::upcast(rayCallback.m_collisionObject);
            if (body)
            {
                Entity * e = FindEntityByRigidBoy(body);
                if (e) return e;
            }
        }

        return nullptr;
    }

    Texture2D *Scene::GetDepthAttachmentTexture2D()
    {
        return Renderer3D::GetDepthAttachmentTexture2D();
    }

    Texture2D *Scene::GetColor0AttachmentTexture2D()
    {
        return Renderer3D::GetColor0AttachmentTexture2D();
    }

    Texture2D *Scene::GetTransparentDepthAttachmentTexture2D()
    {
        return Renderer3D::GetTransparentDepthAttachmentTexture2D();
    }

    Texture2D *Scene::GetTransparentColor0AttachmentTexture2D()
    {
        return Renderer3D::GetTransparentColor0AttachmentTexture2D();
    }

    Texture2D *Scene::GetCustomDepthAttachmentTexture2D()
    {
        if (!m_FramebufferData) return NULL;
        return m_FramebufferData->GetDepthAttachmentTexture2D();
    }

    Texture2D *Scene::GetCustomColor0AttachmentTexture2D()
    {
        if (!m_FramebufferData) return NULL;
        return m_FramebufferData->GetColor0AttachmentTexture2D();
    }

    Texture2D *Scene::GetCustomDepthAttachmentTexture2DFrom2DScene()
    {
        if (!m_FramebufferData2D) return NULL;
        return m_FramebufferData2D->GetDepthAttachmentTexture2D();
    }

    Texture2D *Scene::GetCustomColor0AttachmentTexture2DFrom2DScene()
    {
        if (!m_FramebufferData2D) return NULL;
        return m_FramebufferData2D->GetColor0AttachmentTexture2D();
    }

    Font *Scene::LoadFont(const char *file, std::string name)
    {
        FT_Library ft;
        if (FT_Init_FreeType(&ft))
            std::cout << "ERROR::FREETYPE: Could not init FreeType Library" << std::endl;

        FT_Face face;
        if (FT_New_Face(ft, file, 0, &face))
            std::cout << "ERROR::FREETYPE: Failed to load font:" << file << std::endl;

        m_CurrentFont = new Font();
        m_CurrentFont->face = face;
        m_CurrentFont->ft = ft;
        m_CurrentFont->path = std::string(file);
        m_CurrentFont->name = name;
        return m_CurrentFont;
    }

    Entity * Scene::AddOrthoCameraNode(Entity *parent)
    {
        if (!m_OrthographicCamera)
        {
            m_OrthographicCamera = new OrthographicCamera(0.0, m_ViewportWidth, m_ViewportHeight, 0.0);
        }

        Entity *camera2d = CreateEntity("camera2d", parent);
        m_mainCamera2dEntity = camera2d;
        CameraComponent* c = new CameraComponent((Camera*)m_OrthographicCamera, false, true, true);
        camera2d->AddComponent<CameraComponent>(c);

        return camera2d;
    }

    Entity * Scene::AddPerspectCameraNode(Entity *parent)
    {
        if (!m_PerspectiveCamera)
        {
            m_PerspectiveCamera = new PerspectiveCamera(45.0, m_ViewportWidth / m_ViewportHeight, 0.01, 1000.0);
            m_PerspectiveCamera->SetPosition({0.0f, 0.0f, 20.0f});
            //m_PerspectiveCamera->SetTargetPosition({0.0f, 0.0f, 0.0f});
        }

        if (!m_EditPerspectiveCamera)
        {
            m_EditPerspectiveCamera = new PerspectiveCamera(45.0, m_ViewportWidth / m_ViewportHeight, 0.01, 1000.0);
            m_EditPerspectiveCamera->SetPosition({ 0.0f, 20.0f, 20.0f });
            m_EditPerspectiveCamera->SetTargetPosition({ 0.0f, 0.0f, 0.0f });
            m_EditPerspectiveCamera->SetHasLookAt(true);
        }

        Entity *camera3d = CreateEntity("camera3d", parent);
        m_mainCamera3dEntity = camera3d;
        camera3d->AddComponent<CameraComponent>(new CameraComponent((Camera*)m_PerspectiveCamera, true, false, false));

        return camera3d;
    }

    Entity * Scene::AddPerspectCameraNodeForCamera3d(Entity *parent)
    {
        if (!m_OrthographicCamera3d)
        {
            m_OrthographicCamera3d = new OrthographicCamera(0.0, m_ViewportWidth, m_ViewportHeight, 0.0);
        }

        Entity *camera3d = CreateEntity("camera3d", parent);
        camera3d->AddComponent<CameraComponent>(new CameraComponent((Camera*)m_OrthographicCamera3d, true, false, false));

        return camera3d;
    }

    Entity * Scene::AddLight(Entity *parent)
    {
        Entity *e = CreateEntity("Light", parent);
        LightComponent* light = new LightComponent(glm::vec4(1.0));
        light->Position = glm::vec4(0.0);
        SetLightPos(light->Position);
        SetLightColor(light->Color);

        e->AddComponent<LightComponent>(light);
        return e;
    }

    Entity * Scene::AddImageNode(Entity *parent, std::string path, std::string name)
    {
        //if (!parent)
        //    parent = m_root;
        //std::string num = Tool::Int2Str(parent->GetChildCount());
        Entity *e = CreateEntity(name==""?"Image" : name, parent);

        Material2DComponent* c = new Material2DComponent();
        //c->Texture = Texture2D::Create(PATHCONFIG("assets/textures/DefaultTextureImage.png"));
        if ("" != path) {
            c->Texture = CC::ResourceManager::LoadTexture(path, name);
        }
        else {
            c->Texture = CC::ResourceManager::LoadTexture(PATHCONFIG("assets/textures/DefaultTextureImage.png"), "DefaultTextureImage");
        }
        
        e->AddComponent<Material2DComponent>(c);        

        auto t = e->GetComponent<TransformComponent>(ComponentType_Transform);
        t->Scale = {200.0f, 200.0f, 1.0f};
        t->Translation = {0.0f, 0.0f, 0.0f};
        return e;
    }

    Entity * Scene::AddImageNode(Entity * parent, Texture2D * texture, std::string name)
    {
        //if (!parent)
        //    parent = m_root;
        //std::string num = Tool::Int2Str(parent->GetChildCount());
        Entity *e = CreateEntity(name == "" ? "Image" : name, parent);

        Material2DComponent* c = new Material2DComponent();
        c->Texture = texture;

        e->AddComponent<Material2DComponent>(c);

        auto t = e->GetComponent<TransformComponent>(ComponentType_Transform);
        t->Scale = { 200.0f, 200.0f, 1.0f };
        t->Translation = { 0.0f, 0.0f, 0.0f };
        return e;
    }

    Entity * Scene::AddTextNode(Entity *parent, std::string name)
    {
        //if (!parent)
        //    parent = m_root;
        //std::string num = Tool::Int2Str(parent->GetChildCount());
        Entity *e = CreateEntity(name == "" ? "Text" : name, parent);

        Material2DComponent* c = new Material2DComponent();
        c->Color = { 0.0, 0.0, 0.0, 1.0 };
        e->AddComponent<Material2DComponent>(c);
        
        FontComponent* f = new FontComponent(GetFont());
        e->AddComponent<FontComponent>(f);

        auto t = e->GetComponent<TransformComponent>(ComponentType_Transform);
        t->Scale = { 200.0f, 40.0f, 1.0f };
        t->Translation = { 0.0f, 0.0f, 0.0f };
        return e;
    }

    Entity * Scene::AddTextFpsNode(Entity *parent, std::string name)
    {
        //if (!parent)
        //    parent = m_root;
        //std::string num = Tool::Int2Str(parent->GetChildCount());
        Entity *e = CreateEntity(name == "" ? "TextFps" : name, parent);

        Material2DComponent* c = new Material2DComponent();
        c->Color = { 0.0, 0.0, 0.0, 1.0 };
        e->AddComponent<Material2DComponent>(c);

        FontComponent* f = new FontComponent(GetFont());
        e->AddComponent<FontComponent>(f);

        auto t = e->GetComponent<TransformComponent>(ComponentType_Transform);
        t->Scale = { 100.0f, 40.0f, 1.0f };
        t->Translation = { 0.0f, 0.0f, 0.0f };

        auto tag = e->GetComponent<TagComponent>(ComponentType_Tag);
        tag->Type = TagType_FPS;
        return e;
    }

    Entity * Scene::AddButtonNode(Entity *parent, std::string name)
    {
        //if (!parent)
        //    parent = m_root;
        //std::string num = Tool::Int2Str(parent->GetChildCount());
        Entity *e = CreateEntity(name == "" ? "Button" : name , parent);

        Material2DComponent* c = new Material2DComponent();
        c->Color = { 0.0, 0.0, 0.0, 1.0 };
        e->AddComponent<Material2DComponent>(c);        

        auto t = e->GetComponent<TransformComponent>(ComponentType_Transform);
        t->Scale = { 200.0f, 50.0f, 1.0f };
        t->Translation = { 0.0f, 30.0f, 0.0f };

        MouseAreaComponent* mouseAreaComponent = new MouseAreaComponent();
        e->AddComponent<MouseAreaComponent>(mouseAreaComponent);

        //mouseAreaComponent->AddHandler<MouseButtonPressedEvent>(std::bind(&Scene::OnMouseButtonPressedForButton, this, std::placeholders::_1, std::placeholders::_2));
        //mouseAreaComponent->AddHandler<MouseButtonReleasedEvent>(std::bind(&Scene::OnMouseButtonReleasedForButton, this, std::placeholders::_1, std::placeholders::_2));
        return e;
    }

    Entity * Scene::AddEmptyNode(Entity * parent, std::string name)
    {
        //if (!parent)
        //    parent = m_root;
        //std::string num = Tool::Int2Str(parent->GetChildCount());
        Entity *e = CreateEntity(name == "" ? "Empty" : name , parent);
        return e;
    }

    Entity * Scene::AddBoxNode(Entity *parent, std::string name)
    {
        //if (!parent)
        //    parent = m_root;
        //std::string num = Tool::Int2Str(parent->GetChildCount());
        Entity *e = CreateEntity(name == "" ? "Box" : name, parent);

        MeshBasicMaterialComponent* c = new MeshBasicMaterialComponent();
        //c->Texture = Texture2D::Create(PATHCONFIG("assets/textures/DefaultTextureImage.png"));
        c->Texture = CC::ResourceManager::LoadTexture(PATHCONFIG("assets/textures/DefaultTextureImage.png"), "DefaultTextureImage");
        e->AddComponent<MeshBasicMaterialComponent>(c);
        

        auto t = e->GetComponent<TransformComponent>(ComponentType_Transform);
        t->Translation = {0.0f, 0.0f, 0.0f};
        return e;
    }

    Entity* Scene::AddModelNode(Entity *parent, std::string path, std::string name, TextureType textureType)
    {
        //if (!parent)
        //    parent = m_root;
        //std::string num = Tool::Int2Str(parent->GetChildCount());
        Entity *e = CreateEntity(name == "" ? "Model" : name, parent);
        if(path.empty()){
            path = PATHCONFIG("assets/models/plane.dae");
        }
        ModelComponent* m = new ModelComponent(path);
        e->AddComponent<ModelComponent>(m);

        Model* model = ResourceManager::LoadModel(m->Path.c_str(), name, textureType);
        if (model) {
            e->AddChildByMeshes(model->Meshes);
            e->SetAnimationInfo(model->AnimationInfo);
        }

        auto t = e->GetComponent<TransformComponent>(ComponentType_Transform);
        t->Scale = { 1.0f, 1.0f, 1.0f };
        t->Translation = { 0.0f, 0.0f, 0.0f };
        return e;
    }

    Entity* Scene::AddModelNodeSync(Entity *parent, std::string path, std::string name, TextureType textureType)
    {
        //if (!parent)
        //    parent = m_root;
        //std::string num = Tool::Int2Str(parent->GetChildCount());
        Entity *e = CreateEntity(name == "" ? "ModelSync" : name, parent);
        if (path.empty()) {
            path = PATHCONFIG("assets/models/plane.dae");
        }
        ModelComponent* m = new ModelComponent(path);
        e->AddComponent<ModelComponent>(m);

        auto t = e->GetComponent<TransformComponent>(ComponentType_Transform);
        t->Scale = { 1.0f, 1.0f, 1.0f };
        t->Translation = { 0.0f, 0.0f, 0.0f };
        return e;
    }

    Entity * Scene::AddLine(Entity *parent, std::string name)
    {
        //if (!parent)
        //    parent = m_root;
        //std::string num = Tool::Int2Str(parent->GetChildCount());
        Entity *e = CreateEntity(name == "" ? "Line" : name, parent);

        LineBasicMaterialComponent* c = new LineBasicMaterialComponent(glm::vec4(1.0f, 0.0f, 1.0f, 1.0f));
        auto t = e->AddComponent<LineBasicMaterialComponent>(c);
        return e;
    }

    Entity * Scene::AddSkybox(std::vector<std::string>& files, Entity * parent, std::string name)
    {
        //if (!parent)
        //    parent = m_root;
        //std::string num = Tool::Int2Str(parent->GetChildCount());
        Entity *e = CreateEntity(name == "" ? "Sky" : name, parent);

        TextureCube* t = ResourceManager::LoadTextureCube(files, name);
        t->Names = files;

        MeshCubeMaterialComponent* c = new MeshCubeMaterialComponent(t, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));
        auto tt = e->AddComponent<MeshCubeMaterialComponent>(c);
        return e;
    }

    void Scene::AddScriptComponent(Entity *parent)
    {
        //if (!parent)
        //    parent = m_root;

        ScriptComponent* s = new ScriptComponent("ScriptTest", PATHCONFIG("assets/scripts/ScriptTest.cpp"));
        parent->AddComponent<ScriptComponent>(s);
    }

    void Scene::AddRigidBodyComponent(Entity *parent, RigidBodyShapeType shapeType, glm::vec3 trans, glm::vec3 rotation, glm::vec3 scale, glm::vec3 offset, float mass, Entity* shapeOjbect)
    {
        if (!parent)
            return;

        if(RigidBodyShapeType_Box == shapeType){
            RigidBody _RigidBody = Physics::CreateShapeBox(scale[0], scale[1], scale[2], mass, trans, rotation, offset);
            parent->AddComponent<RigidBodyComponent>(new RigidBodyComponent(_RigidBody));
        }
        else if(RigidBodyShapeType_TriangleMesh == shapeType){

            glm::mat4 model = glm::mat4(1.0);
            model = Tool::ScaleByLocal(model, scale);

            Entity* target = NULL;

            if (shapeOjbect) {
                //simple
                target = shapeOjbect;
            }
            else {
                target = parent;
            }

            int len = target->GetChildCount();
            floatPtr* vertexBase = new floatPtr[len];
            int* numVertices = new int[len];
            uShortPtr* indexBase = new uShortPtr[len];
            int* numIndexes = new int[len];

            int numVerticesSize = 0;
            int numIndexesSize = 0;

            for (int i = 0; i < len; i++) {
                Entity* e = target->GetChild(i);
                auto c = e->GetComponent<MeshComponent>(ComponentType_Mesh);

                int vLen = c->MeshData.Vertices.size();
                int iLen = c->MeshData.Indices.size();
                numVerticesSize += vLen;
                numIndexesSize += iLen;
            }

            //n mesh data->1 mesh data
            floatPtr* vertexBase1 = new floatPtr[1];
            int* numVertices1 = new int[numVerticesSize];
            uShortPtr* indexBase1 = new uShortPtr[1];
            int* numIndexes1 = new int[numIndexesSize];

            float* vertexBaseData1 = new float[numVerticesSize * 3];
            uShortPtr indexBaseData1 = new unsigned short[numIndexesSize];

            vertexBase1[0] = vertexBaseData1;
            indexBase1[0] = indexBaseData1;
            numVertices1[0] = numVerticesSize;
            numIndexes1[0] = numIndexesSize;

            int ivIndex = 0;
            int iivIndex = 0;

            for(int i = 0; i < len; i++){
                Entity* e = target->GetChild(i);
                auto c = e->GetComponent<MeshComponent>(ComponentType_Mesh);

                int vLen = c->MeshData.Vertices.size();
                float* vertexBaseData = new float[vLen*3];
                vertexBase[i] = vertexBaseData;
                numVertices[i] = vLen;   

                int iLen = c->MeshData.Indices.size();
                uShortPtr indexBaseData = new unsigned short[iLen];
                indexBase[i] = indexBaseData;
                numIndexes[i] = iLen;                  

                for(int vIndex = 0; vIndex < vLen; vIndex++){
                    glm::vec3 p0 = c->MeshData.Vertices[vIndex].Position;
                    glm::vec4 p00 = model * glm::vec4(p0[0], p0[1], p0[2], 0.0);

                    vertexBaseData[vIndex * 3] = p00[0];
                    vertexBaseData[vIndex * 3 + 1] = p00[1];
                    vertexBaseData[vIndex * 3 + 2] = p00[2];

                    vertexBaseData1[ivIndex * 3] = p00[0];
                    vertexBaseData1[ivIndex * 3 + 1] = p00[1];
                    vertexBaseData1[ivIndex * 3 + 2] = p00[2];
                    ivIndex += 1;
                }

                for(int vIndex = 0; vIndex < iLen; vIndex++){
                    indexBaseData[vIndex] = (unsigned short)c->MeshData.Indices[vIndex];

                    indexBaseData1[iivIndex] = (unsigned short)c->MeshData.Indices[vIndex];
                    iivIndex += 1;
                }

                delete vertexBaseData;
                delete indexBaseData;
            }
            
            delete vertexBase;
            delete indexBase;
            delete numVertices;
            delete numIndexes;
            
            //RigidBody _RigidBody = Physics::CreateShapeTriangleMesh(len, vertexBase, numVertices, indexBase, numIndexes, 0.0f, glm::vec3(0.0f, 0.0f, 0.0f));
            RigidBody _RigidBody = Physics::CreateShapeTriangleMesh(1, vertexBase1, numVertices1, indexBase1, numIndexes1, 
                mass, trans, rotation, scale, offset);
            parent->AddComponent<RigidBodyComponent>(new RigidBodyComponent(_RigidBody));
        }
        
    }

    void Scene::AddAnimationComponent(Entity *parent /*= nullptr*/)
    {
        if (!parent)
            return;

        CC_CORE_INFO("AddAnimationComponent %s\n", parent->GetComponent<TagComponent>(ComponentType_Tag)->Tag.c_str());
        parent->AddComponent<AnimationComponent>(new AnimationComponent(parent->GetAnimationInfo()));
    }

    void Scene::SetFrameBuffer(Framebuffer * f)
    {
        //if (m_FramebufferData && m_FramebufferData != f) {
        //    delete m_FramebufferData;
        //    m_FramebufferData = nullptr;
        //}
        m_FramebufferData = f;
    }

    void Scene::SetFrameBuffer2D(Framebuffer * f)
    {
        m_FramebufferData2D = f;
    }

    Renderer2D::Statistics Scene::GetStats2D() {
        return Renderer2D::GetStats();
    }
    Renderer3D::Statistics Scene::GetStats3D() {
        return Renderer3D::GetStats();
    }

    void Scene::InitPhysicesWorld()
    {
        /// collision configuration contains default setup for memory, collision setup. Advanced users can create their own configuration.
        collisionConfiguration = new btDefaultCollisionConfiguration();

        /// use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
        dispatcher = new btCollisionDispatcher(collisionConfiguration);

        /// btDbvtBroadphase is a good general purpose broadphase. You can also try out btAxis3Sweep.
        overlappingPairCache = new btDbvtBroadphase();

        /// the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
        solver = new btSequentialImpulseConstraintSolver;

        m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, overlappingPairCache, solver, collisionConfiguration);
    }

    void Scene::ReleasePhysicesWorld()
    {
        // remove the rigidbodies from the dynamics world and delete them
        for (int i = m_dynamicsWorld->getNumCollisionObjects() - 1; i >= 0; i--)
        {
            btCollisionObject *obj = m_dynamicsWorld->getCollisionObjectArray()[i];
            btRigidBody *body = btRigidBody::upcast(obj);
            if (body && body->getMotionState())
            {
                delete body->getMotionState();
            }
            m_dynamicsWorld->removeCollisionObject(obj);
            delete obj;
        }

        // delete collision shapes
        for (int j = 0; j < collisionShapes.size(); j++)
        {
            btCollisionShape *shape = collisionShapes[j];
            collisionShapes[j] = 0;
            delete shape;
        }

        // delete dynamics world
        delete m_dynamicsWorld;

        // delete solver
        delete solver;

        // delete broadphase
        delete overlappingPairCache;

        // delete dispatcher
        delete dispatcher;

        delete collisionConfiguration;

        // next line is optional: it will be cleared by the destructor when the array goes out of scope
        collisionShapes.clear();
    }

    void Scene::InitFontUnicode()
    {
        //ParseUnicode(PATHCONFIG("assets/fonts/unicode.txt"));
    }

    void Scene::OnComponentAdded(Entity *entity, Component* component) {
        if (ComponentType_RigidBody == component->componentType) {
            RigidBodyComponent* c = dynamic_cast<RigidBodyComponent*>(component);
            if (RigidBodyShapeType_Box == c->RigidBodyData.RigidBodyShapeTypeValue) {
                m_dynamicsWorld->addRigidBody(c->RigidBodyData.BtRigidBody);
                collisionShapes.push_back(c->RigidBodyData.BtCollisionShape);
            }
            else if (RigidBodyShapeType_TriangleMesh == c->RigidBodyData.RigidBodyShapeTypeValue) {
                for (int i = 0; i < c->RigidBodyData.BtRigidBodyes.size(); i++) {
                    m_dynamicsWorld->addRigidBody(c->RigidBodyData.BtRigidBodyes[i]);
                }
                for (int i = 0; i < c->RigidBodyData.BtCollisionShapes.size(); i++) {
                    collisionShapes.push_back(c->RigidBodyData.BtCollisionShapes[i]);
                }
            }
        }
        else if(ComponentType_Script == component->componentType) {
            ScriptComponent* c = dynamic_cast<ScriptComponent*>(component);
            c->ScriptObject->node = entity;
            c->ScriptObject->scene = this;
        }
    }

    void Scene::OnComponentRemoved(Entity *entity, Component* component)
    {
        if (ComponentType_RigidBody == component->componentType) {
            RigidBodyComponent* c = dynamic_cast<RigidBodyComponent*>(component);
            if (RigidBodyShapeType_Box == c->RigidBodyData.RigidBodyShapeTypeValue) {
                m_dynamicsWorld->removeRigidBody(c->RigidBodyData.BtRigidBody);
                collisionShapes.remove(c->RigidBodyData.BtCollisionShape);
            }
            else if (RigidBodyShapeType_TriangleMesh == c->RigidBodyData.RigidBodyShapeTypeValue) {
                for (int i = 0; i < c->RigidBodyData.BtRigidBodyes.size(); i++) {
                    m_dynamicsWorld->removeRigidBody(c->RigidBodyData.BtRigidBodyes[i]);
                }
                for (int i = 0; i < c->RigidBodyData.BtCollisionShapes.size(); i++) {
                    collisionShapes.remove(c->RigidBodyData.BtCollisionShapes[i]);
                }
            }
        }
        
    }
}
